Remove rayon_croissant and clean up contains_floats (#29960)

Remove rayon_croissant and refactor the way that information about
floats in flows bubbles up. This simplifies the code a good deal and
lets us take advantage of some more optimized functions provided by
rayon. This removes 2 crates from the dependency tree.

In addition, this allows avoiding passing `contains_floats` up from
every box tree construction function. This makes things simpler, but
also opens up the possibility of passing more of these flags up in the
future (such as `contains_counters`).
This commit is contained in:
Martin Robinson 2023-07-19 09:01:55 +02:00 committed by GitHub
parent 9c333ab1ee
commit 4f4c2a5922
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 108 additions and 144 deletions

17
Cargo.lock generated
View file

@ -3051,7 +3051,6 @@ dependencies = [
"quickcheck",
"range",
"rayon",
"rayon_croissant",
"script_layout_interface",
"script_traits",
"serde",
@ -3688,12 +3687,6 @@ version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9de3eca27871df31c33b807f834b94ef7d000956f57aa25c5aed9c5f0aae8f6f"
[[package]]
name = "moite_moite"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eeb5a94c61e12e2cfc16ee3e2b6eca8f126a43c888586626337544a7e824a1af"
[[package]]
name = "mozangle"
version = "0.3.5"
@ -4814,16 +4807,6 @@ dependencies = [
"num_cpus",
]
[[package]]
name = "rayon_croissant"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e4aafda434bd10fec689858e2b1d713d0b784b1e60df3761ac8fa727d7e8e27"
dependencies = [
"moite_moite",
"rayon",
]
[[package]]
name = "redox_syscall"
version = "0.2.13"

View file

@ -34,7 +34,6 @@ net_traits = { path = "../net_traits" }
parking_lot = { workspace = true }
range = { path = "../range" }
rayon = { workspace = true }
rayon_croissant = "0.2.0"
script_layout_interface = { path = "../script_layout_interface" }
script_traits = { path = "../script_traits" }
serde = { workspace = true }

View file

@ -13,7 +13,6 @@ use crate::formatting_contexts::IndependentFormattingContext;
use crate::positioned::AbsolutelyPositionedBox;
use crate::style_ext::{ComputedValuesExt, DisplayGeneratingBox, DisplayInside, DisplayOutside};
use rayon::iter::{IntoParallelIterator, ParallelIterator};
use rayon_croissant::ParallelIteratorExt;
use servo_arc::Arc;
use std::borrow::Cow;
use std::convert::{TryFrom, TryInto};
@ -34,18 +33,19 @@ impl BlockFormattingContext {
where
Node: NodeExt<'dom>,
{
let (contents, contains_floats) = BlockContainer::construct(
let contents = BlockContainer::construct(
context,
info,
contents,
propagated_text_decoration_line,
is_list_item,
);
let bfc = Self {
let contains_floats = contents.contains_floats();
Self {
contents,
contains_floats: contains_floats == ContainsFloats::Yes,
};
bfc
contains_floats,
}
}
pub fn construct_for_text_runs<'dom>(
@ -61,6 +61,7 @@ impl BlockFormattingContext {
inline_level_boxes,
text_decoration_line,
has_first_formatted_line: true,
contains_floats: false,
};
let contents = BlockContainer::InlineFormattingContext(ifc);
let bfc = Self {
@ -163,9 +164,6 @@ struct BlockContainerBuilder<'dom, 'style, Node> {
/// The style of the anonymous block boxes pushed to the list of block-level
/// boxes, if any (see `end_ongoing_inline_formatting_context`).
anonymous_style: Option<Arc<ComputedValues>>,
/// Whether the resulting block container contains any float box.
contains_floats: ContainsFloats,
}
impl BlockContainer {
@ -175,7 +173,7 @@ impl BlockContainer {
contents: NonReplacedContents,
propagated_text_decoration_line: TextDecorationLine,
is_list_item: bool,
) -> (BlockContainer, ContainsFloats)
) -> BlockContainer
where
Node: NodeExt<'dom>,
{
@ -191,7 +189,6 @@ impl BlockContainer {
),
ongoing_inline_boxes_stack: Vec::new(),
anonymous_style: None,
contains_floats: ContainsFloats::No,
};
if is_list_item {
@ -222,43 +219,28 @@ impl BlockContainer {
.is_empty()
{
if builder.block_level_boxes.is_empty() {
let container = BlockContainer::InlineFormattingContext(
return BlockContainer::InlineFormattingContext(
builder.ongoing_inline_formatting_context,
);
return (container, builder.contains_floats);
}
builder.end_ongoing_inline_formatting_context();
}
let mut contains_floats = builder.contains_floats;
let mapfold = |contains_floats: &mut ContainsFloats, creator: BlockLevelJob<'dom, _>| {
let (block_level_box, box_contains_floats) = creator.finish(context);
*contains_floats |= box_contains_floats;
block_level_box
};
let block_level_boxes = if context.use_rayon {
builder
.block_level_boxes
.into_par_iter()
.mapfold_reduce_into(
&mut contains_floats,
mapfold,
|| ContainsFloats::No,
|left, right| {
*left |= right;
},
)
.map(|block_level_job| block_level_job.finish(context))
.collect()
} else {
builder
.block_level_boxes
.into_iter()
.map(|x| mapfold(&mut contains_floats, x))
.map(|block_level_job| block_level_job.finish(context))
.collect()
};
let container = BlockContainer::BlockLevelBoxes(block_level_boxes);
(container, contains_floats)
BlockContainer::BlockLevelBoxes(block_level_boxes)
}
}
@ -662,8 +644,6 @@ where
contents: Contents,
box_slot: BoxSlot<'dom>,
) {
self.contains_floats = ContainsFloats::Yes;
if !self.has_ongoing_inline_formatting_context() {
let kind = BlockLevelCreator::OutOfFlowFloatBox {
contents,
@ -681,6 +661,7 @@ where
display_inside,
contents,
)));
self.ongoing_inline_formatting_context.contains_floats = true;
self.current_inline_level_boxes().push(box_.clone());
box_slot.set(LayoutBox::InlineLevel(box_))
}
@ -748,17 +729,18 @@ impl<'dom, Node> BlockLevelJob<'dom, Node>
where
Node: NodeExt<'dom>,
{
fn finish(self, context: &LayoutContext) -> (ArcRefCell<BlockLevelBox>, ContainsFloats) {
fn finish(self, context: &LayoutContext) -> ArcRefCell<BlockLevelBox> {
let info = &self.info;
let (block_level_box, contains_floats) = match self.kind {
BlockLevelCreator::SameFormattingContextBlock(contents) => {
let (contents, contains_floats) = contents.finish(context, info);
let block_level_box = ArcRefCell::new(BlockLevelBox::SameFormattingContextBlock {
let block_level_box = match self.kind {
BlockLevelCreator::SameFormattingContextBlock(intermediate_block_container) => {
let contents = intermediate_block_container.finish(context, info);
let contains_floats = contents.contains_floats();
ArcRefCell::new(BlockLevelBox::SameFormattingContextBlock {
base_fragment_info: info.into(),
contents,
style: Arc::clone(&info.style),
});
(block_level_box, contains_floats)
contains_floats,
})
},
BlockLevelCreator::Independent {
display_inside,
@ -772,35 +754,32 @@ where
contents,
propagated_text_decoration_line,
);
(
ArcRefCell::new(BlockLevelBox::Independent(context)),
ContainsFloats::No,
)
ArcRefCell::new(BlockLevelBox::Independent(context))
},
BlockLevelCreator::OutOfFlowAbsolutelyPositionedBox {
display_inside,
contents,
} => {
let block_level_box = ArcRefCell::new(
BlockLevelBox::OutOfFlowAbsolutelyPositionedBox(ArcRefCell::new(
AbsolutelyPositionedBox::construct(context, info, display_inside, contents),
)),
);
(block_level_box, ContainsFloats::No)
},
} => ArcRefCell::new(BlockLevelBox::OutOfFlowAbsolutelyPositionedBox(
ArcRefCell::new(AbsolutelyPositionedBox::construct(
context,
info,
display_inside,
contents,
)),
)),
BlockLevelCreator::OutOfFlowFloatBox {
display_inside,
contents,
} => {
let block_level_box = ArcRefCell::new(BlockLevelBox::OutOfFlowFloatBox(
FloatBox::construct(context, info, display_inside, contents),
));
(block_level_box, ContainsFloats::Yes)
},
} => ArcRefCell::new(BlockLevelBox::OutOfFlowFloatBox(FloatBox::construct(
context,
info,
display_inside,
contents,
))),
};
self.box_slot
.set(LayoutBox::BlockLevel(block_level_box.clone()));
(block_level_box, contains_floats)
block_level_box
}
}
@ -809,7 +788,7 @@ impl IntermediateBlockContainer {
self,
context: &LayoutContext,
info: &NodeAndStyleInfo<Node>,
) -> (BlockContainer, ContainsFloats)
) -> BlockContainer
where
Node: NodeExt<'dom>,
{
@ -826,28 +805,8 @@ impl IntermediateBlockContainer {
is_list_item,
),
IntermediateBlockContainer::InlineFormattingContext(ifc) => {
// If that inline formatting context contained any float, those
// were already taken into account during the first phase of
// box construction.
(
BlockContainer::InlineFormattingContext(ifc),
ContainsFloats::No,
)
BlockContainer::InlineFormattingContext(ifc)
},
}
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub(crate) enum ContainsFloats {
No,
Yes,
}
impl std::ops::BitOrAssign for ContainsFloats {
fn bitor_assign(&mut self, other: Self) {
if other == ContainsFloats::Yes {
*self = ContainsFloats::Yes;
}
}
}

View file

@ -39,6 +39,7 @@ pub(crate) struct InlineFormattingContext {
// Whether this IFC contains the 1st formatted line of an element
// https://www.w3.org/TR/css-pseudo-4/#first-formatted-line
pub(super) has_first_formatted_line: bool,
pub(super) contains_floats: bool,
}
#[derive(Debug, Serialize)]
@ -172,6 +173,7 @@ impl InlineFormattingContext {
inline_level_boxes: Default::default(),
text_decoration_line,
has_first_formatted_line,
contains_floats: false,
}
}

View file

@ -49,6 +49,17 @@ pub(crate) enum BlockContainer {
InlineFormattingContext(InlineFormattingContext),
}
impl BlockContainer {
fn contains_floats(&self) -> bool {
match self {
BlockContainer::BlockLevelBoxes(boxes) => boxes
.iter()
.any(|block_level_box| block_level_box.borrow().contains_floats()),
BlockContainer::InlineFormattingContext { .. } => true,
}
}
}
#[derive(Debug, Serialize)]
pub(crate) enum BlockLevelBox {
SameFormattingContextBlock {
@ -56,6 +67,7 @@ pub(crate) enum BlockLevelBox {
#[serde(skip_serializing)]
style: Arc<ComputedValues>,
contents: BlockContainer,
contains_floats: bool,
},
OutOfFlowAbsolutelyPositionedBox(ArcRefCell<AbsolutelyPositionedBox>),
OutOfFlowFloatBox(FloatBox),
@ -63,6 +75,16 @@ pub(crate) enum BlockLevelBox {
}
impl BlockLevelBox {
fn contains_floats(&self) -> bool {
match self {
BlockLevelBox::SameFormattingContextBlock {
contains_floats, ..
} => *contains_floats,
BlockLevelBox::OutOfFlowFloatBox { .. } => true,
_ => false,
}
}
fn find_block_margin_collapsing_with_parent(
&self,
collected_margin: &mut CollapsedMargin,
@ -496,6 +518,7 @@ impl BlockLevelBox {
base_fragment_info: tag,
style,
contents,
..
} => Fragment::Box(positioning_context.layout_maybe_position_relative_fragment(
layout_context,
containing_block,

View file

@ -7,7 +7,6 @@ use crate::context::LayoutContext;
use crate::dom::{LayoutBox, NodeExt};
use crate::dom_traversal::{iter_child_nodes, Contents, NodeAndStyleInfo};
use crate::flexbox::FlexLevelBox;
use crate::flow::construct::ContainsFloats;
use crate::flow::float::FloatBox;
use crate::flow::inline::InlineLevelBox;
use crate::flow::{BlockContainer, BlockFormattingContext, BlockLevelBox};
@ -45,15 +44,17 @@ impl BoxTree {
where
Node: 'dom + Copy + LayoutNode<'dom> + Send + Sync,
{
let (contains_floats, boxes) = construct_for_root_element(&context, root_element);
let boxes = construct_for_root_element(&context, root_element);
// Zero box for `:root { display: none }`, one for the root element otherwise.
assert!(boxes.len() <= 1);
let contents = BlockContainer::BlockLevelBoxes(boxes);
let contains_floats = contents.contains_floats();
Self {
root: BlockFormattingContext {
contains_floats: contains_floats == ContainsFloats::Yes,
contents: BlockContainer::BlockLevelBoxes(boxes),
contents,
contains_floats,
},
canvas_background: CanvasBackground::for_root_element(context, root_element),
}
@ -209,14 +210,14 @@ impl BoxTree {
fn construct_for_root_element<'dom>(
context: &LayoutContext,
root_element: impl NodeExt<'dom>,
) -> (ContainsFloats, Vec<ArcRefCell<BlockLevelBox>>) {
) -> Vec<ArcRefCell<BlockLevelBox>> {
let info = NodeAndStyleInfo::new(root_element, root_element.style(context));
let box_style = info.style.get_box();
let display_inside = match Display::from(box_style.display) {
Display::None => {
root_element.unset_all_boxes();
return (ContainsFloats::No, Vec::new());
return Vec::new();
},
Display::Contents => {
// Unreachable because the style crate adjusts the computed values:
@ -230,41 +231,32 @@ fn construct_for_root_element<'dom>(
let contents =
ReplacedContent::for_element(root_element).map_or(Contents::OfElement, Contents::Replaced);
let (contains_floats, root_box) = if box_style.position.is_absolutely_positioned() {
(
ContainsFloats::No,
BlockLevelBox::OutOfFlowAbsolutelyPositionedBox(ArcRefCell::new(
AbsolutelyPositionedBox::construct(context, &info, display_inside, contents),
)),
)
let root_box = if box_style.position.is_absolutely_positioned() {
BlockLevelBox::OutOfFlowAbsolutelyPositionedBox(ArcRefCell::new(
AbsolutelyPositionedBox::construct(context, &info, display_inside, contents),
))
} else if box_style.float.is_floating() {
(
ContainsFloats::Yes,
BlockLevelBox::OutOfFlowFloatBox(FloatBox::construct(
context,
&info,
display_inside,
contents,
)),
)
BlockLevelBox::OutOfFlowFloatBox(FloatBox::construct(
context,
&info,
display_inside,
contents,
))
} else {
let propagated_text_decoration_line = info.style.clone_text_decoration_line();
(
ContainsFloats::No,
BlockLevelBox::Independent(IndependentFormattingContext::construct(
context,
&info,
display_inside,
contents,
propagated_text_decoration_line,
)),
)
BlockLevelBox::Independent(IndependentFormattingContext::construct(
context,
&info,
display_inside,
contents,
propagated_text_decoration_line,
))
};
let root_box = ArcRefCell::new(root_box);
root_element
.element_box_slot()
.set(LayoutBox::BlockLevel(root_box.clone()));
(contains_floats, vec![root_box])
vec![root_box]
}
impl BoxTree {

View file

@ -14,8 +14,8 @@ use crate::geom::flow_relative::{Rect, Sides, Vec2};
use crate::geom::{LengthOrAuto, LengthPercentageOrAuto};
use crate::style_ext::{ComputedValuesExt, DisplayInside};
use crate::{ContainingBlock, DefiniteContainingBlock};
use rayon::iter::{IntoParallelRefMutIterator, ParallelExtend};
use rayon_croissant::ParallelIteratorExt;
use rayon::iter::IntoParallelRefMutIterator;
use rayon::prelude::{IndexedParallelIterator, ParallelIterator};
use style::computed_values::position::T as Position;
use style::properties::ComputedValues;
use style::values::computed::{CSSPixelLength, Length};
@ -354,21 +354,27 @@ impl HoistedAbsolutelyPositionedBox {
containing_block: &DefiniteContainingBlock,
) {
if layout_context.use_rayon {
fragments.par_extend(boxes.par_iter_mut().mapfold_reduce_into(
for_nearest_containing_block_for_all_descendants,
|for_nearest_containing_block_for_all_descendants, box_| {
let new_fragment = ArcRefCell::new(Fragment::Box(box_.layout(
let mut new_fragments = Vec::new();
let mut new_hoisted_boxes = Vec::new();
boxes
.par_iter_mut()
.map(|hoisted_box| {
let mut new_hoisted_boxes: Vec<HoistedAbsolutelyPositionedBox> = Vec::new();
let new_fragment = ArcRefCell::new(Fragment::Box(hoisted_box.layout(
layout_context,
for_nearest_containing_block_for_all_descendants,
&mut new_hoisted_boxes,
containing_block,
)));
box_.fragment.borrow_mut().fragment = Some(new_fragment.clone());
new_fragment
},
Vec::new,
vec_append_owned,
))
hoisted_box.fragment.borrow_mut().fragment = Some(new_fragment.clone());
(new_fragment, new_hoisted_boxes)
})
.unzip_into_vecs(&mut new_fragments, &mut new_hoisted_boxes);
fragments.extend(new_fragments);
for_nearest_containing_block_for_all_descendants
.extend(new_hoisted_boxes.into_iter().flatten());
} else {
fragments.extend(boxes.iter_mut().map(|box_| {
let new_fragment = ArcRefCell::new(Fragment::Box(box_.layout(