Skip to content

Commit

Permalink
Store abspos boxes in a RefCell too
Browse files Browse the repository at this point in the history
We want to mutate them when lazily computing their content sizes, but they
are behind an Arc for the hoisting infra, so it also needs its own layer
of inner mutability.
  • Loading branch information
nox committed Jun 9, 2020
1 parent e044d85 commit e975d24
Show file tree
Hide file tree
Showing 7 changed files with 65 additions and 53 deletions.
11 changes: 5 additions & 6 deletions components/layout_2020/flexbox.rs
Expand Up @@ -15,7 +15,6 @@ use crate::sizing::{BoxContentSizes, ContentSizes, ContentSizesRequest};
use crate::style_ext::DisplayGeneratingBox;
use crate::ContainingBlock;
use rayon::iter::{IntoParallelIterator, ParallelIterator};
use servo_arc::Arc;
use std::borrow::Cow;
use style::values::computed::Length;
use style::values::specified::text::TextDecorationLine;
Expand All @@ -31,7 +30,7 @@ pub(crate) struct FlexContainer {
#[derive(Debug, Serialize)]
pub(crate) enum FlexLevelBox {
FlexItem(IndependentFormattingContext),
OutOfFlowAbsolutelyPositionedBox(Arc<AbsolutelyPositionedBox>),
OutOfFlowAbsolutelyPositionedBox(ArcRefCell<AbsolutelyPositionedBox>),
}

impl FlexContainer {
Expand Down Expand Up @@ -192,14 +191,14 @@ where
};
let box_ = if info.style.get_box().position.is_absolutely_positioned() {
// https://drafts.csswg.org/css-flexbox/#abspos-items
ArcRefCell::new(FlexLevelBox::OutOfFlowAbsolutelyPositionedBox(Arc::new(
AbsolutelyPositionedBox::construct(
ArcRefCell::new(FlexLevelBox::OutOfFlowAbsolutelyPositionedBox(
ArcRefCell::new(AbsolutelyPositionedBox::construct(
self.context,
&info,
display_inside,
contents,
),
)))
)),
))
} else {
ArcRefCell::new(FlexLevelBox::FlexItem(
IndependentFormattingContext::construct(
Expand Down
18 changes: 12 additions & 6 deletions components/layout_2020/flow/construct.rs
Expand Up @@ -571,9 +571,14 @@ where
kind,
});
} else {
let box_ = ArcRefCell::new(InlineLevelBox::OutOfFlowAbsolutelyPositionedBox(Arc::new(
AbsolutelyPositionedBox::construct(self.context, info, display_inside, contents),
)));
let box_ = ArcRefCell::new(InlineLevelBox::OutOfFlowAbsolutelyPositionedBox(
ArcRefCell::new(AbsolutelyPositionedBox::construct(
self.context,
info,
display_inside,
contents,
)),
));
self.current_inline_level_boxes().push(box_.clone());
box_slot.set(LayoutBox::InlineLevel(box_))
}
Expand Down Expand Up @@ -722,10 +727,11 @@ where
display_inside,
contents,
} => {
let block_level_box =
ArcRefCell::new(BlockLevelBox::OutOfFlowAbsolutelyPositionedBox(Arc::new(
let block_level_box = ArcRefCell::new(
BlockLevelBox::OutOfFlowAbsolutelyPositionedBox(ArcRefCell::new(
AbsolutelyPositionedBox::construct(context, info, display_inside, contents),
)));
)),
);
(block_level_box, ContainsFloats::No)
},
BlockLevelCreator::OutOfFlowFloatBox {
Expand Down
8 changes: 5 additions & 3 deletions components/layout_2020/flow/inline.rs
Expand Up @@ -20,6 +20,7 @@ use crate::sizing::ContentSizes;
use crate::style_ext::{ComputedValuesExt, Display, DisplayGeneratingBox, DisplayOutside};
use crate::ContainingBlock;
use app_units::Au;
use atomic_refcell::AtomicRef;
use gfx::text::text_run::GlyphRun;
use servo_arc::Arc;
use style::properties::ComputedValues;
Expand All @@ -39,7 +40,7 @@ pub(crate) struct InlineFormattingContext {
pub(crate) enum InlineLevelBox {
InlineBox(InlineBox),
TextRun(TextRun),
OutOfFlowAbsolutelyPositionedBox(Arc<AbsolutelyPositionedBox>),
OutOfFlowAbsolutelyPositionedBox(ArcRefCell<AbsolutelyPositionedBox>),
OutOfFlowFloatBox(FloatBox),
Atomic(IndependentFormattingContext),
}
Expand Down Expand Up @@ -283,8 +284,9 @@ impl InlineFormattingContext {
InlineLevelBox::TextRun(run) => run.layout(layout_context, &mut ifc),
InlineLevelBox::Atomic(a) => layout_atomic(layout_context, &mut ifc, a),
InlineLevelBox::OutOfFlowAbsolutelyPositionedBox(box_) => {
let style = AtomicRef::map(box_.borrow(), |box_| &box_.contents.style);
let initial_start_corner =
match Display::from(box_.contents.style.get_box().original_display) {
match Display::from(style.get_box().original_display) {
Display::GeneratingBox(DisplayGeneratingBox::OutsideInside {
outside,
inside: _,
Expand Down Expand Up @@ -313,7 +315,7 @@ impl InlineFormattingContext {
Fragment::AbsoluteOrFixedPositioned(
AbsoluteOrFixedPositionedFragment {
hoisted_fragment,
position: box_.contents.style.clone_position(),
position: style.clone_position(),
},
),
);
Expand Down
4 changes: 2 additions & 2 deletions components/layout_2020/flow/mod.rs
Expand Up @@ -52,7 +52,7 @@ pub(crate) enum BlockLevelBox {
style: Arc<ComputedValues>,
contents: BlockContainer,
},
OutOfFlowAbsolutelyPositionedBox(Arc<AbsolutelyPositionedBox>),
OutOfFlowAbsolutelyPositionedBox(ArcRefCell<AbsolutelyPositionedBox>),
OutOfFlowFloatBox(FloatBox),
Independent(IndependentFormattingContext),
}
Expand Down Expand Up @@ -322,7 +322,7 @@ impl BlockLevelBox {
positioning_context.push(hoisted_box);
Fragment::AbsoluteOrFixedPositioned(AbsoluteOrFixedPositionedFragment {
hoisted_fragment,
position: box_.contents.style.clone_position(),
position: box_.borrow().contents.style.clone_position(),
})
},
BlockLevelBox::OutOfFlowFloatBox(_box_) => {
Expand Down
4 changes: 2 additions & 2 deletions components/layout_2020/flow/root.rs
Expand Up @@ -207,7 +207,7 @@ impl BoxTree {
let contents = ReplacedContent::for_element(dirty_node)
.map_or(Contents::OfElement, Contents::Replaced);
let info = NodeAndStyleInfo::new(dirty_node, Arc::clone(&primary_style));
let out_of_flow_absolutely_positioned_box = Arc::new(
let out_of_flow_absolutely_positioned_box = ArcRefCell::new(
AbsolutelyPositionedBox::construct(context, &info, display_inside, contents),
);
match update_point {
Expand Down Expand Up @@ -267,7 +267,7 @@ fn construct_for_root_element<'dom>(
let (contains_floats, root_box) = if box_style.position.is_absolutely_positioned() {
(
ContainsFloats::No,
BlockLevelBox::OutOfFlowAbsolutelyPositionedBox(Arc::new(
BlockLevelBox::OutOfFlowAbsolutelyPositionedBox(ArcRefCell::new(
AbsolutelyPositionedBox::construct(context, &info, display_inside, contents),
)),
)
Expand Down
57 changes: 31 additions & 26 deletions components/layout_2020/positioned.rs
Expand Up @@ -12,9 +12,8 @@ use crate::geom::{LengthOrAuto, LengthPercentageOrAuto};
use crate::sizing::ContentSizesRequest;
use crate::style_ext::{ComputedValuesExt, DisplayInside};
use crate::{ContainingBlock, DefiniteContainingBlock};
use rayon::iter::{IntoParallelRefIterator, ParallelExtend};
use rayon::iter::{IntoParallelRefMutIterator, ParallelExtend};
use rayon_croissant::ParallelIteratorExt;
use servo_arc::Arc;
use style::computed_values::position::T as Position;
use style::properties::ComputedValues;
use style::values::computed::{Length, LengthPercentage};
Expand All @@ -36,7 +35,7 @@ pub(crate) struct PositioningContext {
}

pub(crate) struct HoistedAbsolutelyPositionedBox {
absolutely_positioned_box: Arc<AbsolutelyPositionedBox>,
absolutely_positioned_box: ArcRefCell<AbsolutelyPositionedBox>,

/// The rank of the child from which this absolutely positioned fragment
/// came from, when doing the layout of a block container. Used to compute
Expand Down Expand Up @@ -98,14 +97,14 @@ impl AbsolutelyPositionedBox {
}

pub(crate) fn to_hoisted(
self_: Arc<Self>,
self_: ArcRefCell<Self>,
initial_start_corner: Vec2<Length>,
tree_rank: usize,
) -> HoistedAbsolutelyPositionedBox {
fn absolute_box_offsets(
initial_static_start: Length,
start: LengthPercentageOrAuto,
end: LengthPercentageOrAuto,
start: LengthPercentageOrAuto<'_>,
end: LengthPercentageOrAuto<'_>,
) -> AbsoluteBoxOffsets {
match (start.non_auto(), end.non_auto()) {
(None, None) => AbsoluteBoxOffsets::StaticStart {
Expand All @@ -122,10 +121,10 @@ impl AbsolutelyPositionedBox {
}
}

let box_offsets = self_.contents.style.box_offsets();
HoistedAbsolutelyPositionedBox {
tree_rank,
box_offsets: Vec2 {
let box_offsets = {
let box_ = self_.borrow();
let box_offsets = box_.contents.style.box_offsets();
Vec2 {
inline: absolute_box_offsets(
initial_start_corner.inline,
box_offsets.inline_start,
Expand All @@ -136,7 +135,11 @@ impl AbsolutelyPositionedBox {
box_offsets.block_start,
box_offsets.block_end,
),
},
}
};
HoistedAbsolutelyPositionedBox {
tree_rank,
box_offsets,
fragment: ArcRefCell::new(None),
absolutely_positioned_box: self_,
}
Expand Down Expand Up @@ -268,7 +271,7 @@ impl PositioningContext {
while !hoisted_boxes.is_empty() {
HoistedAbsolutelyPositionedBox::layout_many(
layout_context,
&hoisted_boxes,
&mut hoisted_boxes,
&mut laid_out_child_fragments,
&mut self.for_nearest_containing_block_for_all_descendants,
&containing_block,
Expand All @@ -281,12 +284,13 @@ impl PositioningContext {

pub(crate) fn push(&mut self, box_: HoistedAbsolutelyPositionedBox) {
if let Some(nearest) = &mut self.for_nearest_positioned_ancestor {
match box_
let position = box_
.absolutely_positioned_box
.borrow()
.contents
.style
.clone_position()
{
.clone_position();
match position {
Position::Fixed => {}, // fall through
Position::Absolute => return nearest.push(box_),
Position::Static | Position::Relative => unreachable!(),
Expand Down Expand Up @@ -357,7 +361,7 @@ impl PositioningContext {
{
HoistedAbsolutelyPositionedBox::layout_many(
layout_context,
&std::mem::take(&mut self.for_nearest_containing_block_for_all_descendants),
&mut std::mem::take(&mut self.for_nearest_containing_block_for_all_descendants),
fragments,
&mut self.for_nearest_containing_block_for_all_descendants,
initial_containing_block,
Expand All @@ -369,13 +373,13 @@ impl PositioningContext {
impl HoistedAbsolutelyPositionedBox {
pub(crate) fn layout_many(
layout_context: &LayoutContext,
boxes: &[Self],
boxes: &mut [Self],
fragments: &mut Vec<ArcRefCell<Fragment>>,
for_nearest_containing_block_for_all_descendants: &mut Vec<HoistedAbsolutelyPositionedBox>,
containing_block: &DefiniteContainingBlock,
) {
if layout_context.use_rayon {
fragments.par_extend(boxes.par_iter().mapfold_reduce_into(
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(
Expand All @@ -391,7 +395,7 @@ impl HoistedAbsolutelyPositionedBox {
vec_append_owned,
))
} else {
fragments.extend(boxes.iter().map(|box_| {
fragments.extend(boxes.iter_mut().map(|box_| {
let new_fragment = ArcRefCell::new(Fragment::Box(box_.layout(
layout_context,
for_nearest_containing_block_for_all_descendants,
Expand All @@ -404,19 +408,20 @@ impl HoistedAbsolutelyPositionedBox {
}

pub(crate) fn layout(
&self,
&mut self,
layout_context: &LayoutContext,
for_nearest_containing_block_for_all_descendants: &mut Vec<HoistedAbsolutelyPositionedBox>,
containing_block: &DefiniteContainingBlock,
) -> BoxFragment {
let cbis = containing_block.size.inline;
let cbbs = containing_block.size.block;
let style = &self.absolutely_positioned_box.contents.style;
let absolutely_positioned_box = self.absolutely_positioned_box.borrow_mut();
let style = &absolutely_positioned_box.contents.style;
let pbm = style.padding_border_margin(&containing_block.into());

let size;
let replaced_used_size;
match self.absolutely_positioned_box.contents.as_replaced() {
match absolutely_positioned_box.contents.as_replaced() {
Ok(replaced) => {
// https://drafts.csswg.org/css2/visudet.html#abs-replaced-width
// https://drafts.csswg.org/css2/visudet.html#abs-replaced-height
Expand Down Expand Up @@ -468,11 +473,11 @@ impl HoistedAbsolutelyPositionedBox {
|positioning_context| {
let size;
let fragments;
match self.absolutely_positioned_box.contents.as_replaced() {
match absolutely_positioned_box.contents.as_replaced() {
Ok(replaced) => {
// https://drafts.csswg.org/css2/visudet.html#abs-replaced-width
// https://drafts.csswg.org/css2/visudet.html#abs-replaced-height
let style = &self.absolutely_positioned_box.contents.style;
let style = &absolutely_positioned_box.contents.style;
size = replaced_used_size.unwrap();
fragments = replaced.make_fragments(style, size.clone());
},
Expand All @@ -488,7 +493,7 @@ impl HoistedAbsolutelyPositionedBox {
anchor -
pbm.padding_border_sums.inline -
margin.inline_sum();
self.absolutely_positioned_box
absolutely_positioned_box
.contents
.content_sizes
.shrink_to_fit(available_size)
Expand Down Expand Up @@ -544,7 +549,7 @@ impl HoistedAbsolutelyPositionedBox {
};

BoxFragment::new(
self.absolutely_positioned_box.contents.tag,
absolutely_positioned_box.contents.tag,
style.clone(),
fragments,
content_rect,
Expand Down
16 changes: 8 additions & 8 deletions components/layout_2020/style_ext.rs
Expand Up @@ -64,9 +64,9 @@ pub(crate) struct PaddingBorderMargin {
pub(crate) trait ComputedValuesExt {
fn inline_size_is_length(&self) -> bool;
fn inline_box_offsets_are_both_non_auto(&self) -> bool;
fn box_offsets(&self) -> flow_relative::Sides<LengthPercentageOrAuto>;
fn box_size(&self) -> flow_relative::Vec2<LengthPercentageOrAuto>;
fn min_box_size(&self) -> flow_relative::Vec2<LengthPercentageOrAuto>;
fn box_offsets(&self) -> flow_relative::Sides<LengthPercentageOrAuto<'_>>;
fn box_size(&self) -> flow_relative::Vec2<LengthPercentageOrAuto<'_>>;
fn min_box_size(&self) -> flow_relative::Vec2<LengthPercentageOrAuto<'_>>;
fn max_box_size(&self) -> flow_relative::Vec2<Option<&LengthPercentage>>;
fn content_box_size(
&self,
Expand All @@ -86,7 +86,7 @@ pub(crate) trait ComputedValuesExt {
fn padding_border_margin(&self, containing_block: &ContainingBlock) -> PaddingBorderMargin;
fn padding(&self) -> flow_relative::Sides<&LengthPercentage>;
fn border_width(&self) -> flow_relative::Sides<Length>;
fn margin(&self) -> flow_relative::Sides<LengthPercentageOrAuto>;
fn margin(&self) -> flow_relative::Sides<LengthPercentageOrAuto<'_>>;
fn has_transform_or_perspective(&self) -> bool;
fn effective_z_index(&self) -> i32;
fn establishes_stacking_context(&self) -> bool;
Expand Down Expand Up @@ -117,7 +117,7 @@ impl ComputedValuesExt for ComputedValues {
!a.is_auto() && !b.is_auto()
}

fn box_offsets(&self) -> flow_relative::Sides<LengthPercentageOrAuto> {
fn box_offsets(&self) -> flow_relative::Sides<LengthPercentageOrAuto<'_>> {
let position = self.get_position();
flow_relative::Sides::from_physical(
&PhysicalSides::new(
Expand All @@ -130,7 +130,7 @@ impl ComputedValuesExt for ComputedValues {
)
}

fn box_size(&self) -> flow_relative::Vec2<LengthPercentageOrAuto> {
fn box_size(&self) -> flow_relative::Vec2<LengthPercentageOrAuto<'_>> {
let position = self.get_position();
flow_relative::Vec2::from_physical_size(
&PhysicalSize::new(
Expand All @@ -141,7 +141,7 @@ impl ComputedValuesExt for ComputedValues {
)
}

fn min_box_size(&self) -> flow_relative::Vec2<LengthPercentageOrAuto> {
fn min_box_size(&self) -> flow_relative::Vec2<LengthPercentageOrAuto<'_>> {
let position = self.get_position();
flow_relative::Vec2::from_physical_size(
&PhysicalSize::new(
Expand Down Expand Up @@ -271,7 +271,7 @@ impl ComputedValuesExt for ComputedValues {
)
}

fn margin(&self) -> flow_relative::Sides<LengthPercentageOrAuto> {
fn margin(&self) -> flow_relative::Sides<LengthPercentageOrAuto<'_>> {
let margin = self.get_margin();
flow_relative::Sides::from_physical(
&PhysicalSides::new(
Expand Down

0 comments on commit e975d24

Please sign in to comment.