layout: Make Fragment hold ArcRefCell inside (#34923)

Push the interior mutability into enum variants of `Fragment`, so that
they can be cloned. This saves memory in the `Fragment` tree as the
`Fragment` enum is now a relatively wee 16 bytes and the interior parts
can be a variety of sizes. Before, every `Fragment` was the size of the
biggest kind (`BoxFragment` - 248 bytes).

This a step on the way toward incremental layout.

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Co-authored-by: Oriol Brufau <obrufau@igalia.com>
This commit is contained in:
Martin Robinson 2025-01-13 10:59:59 +01:00 committed by GitHub
parent c936dd6c4e
commit de780dcde4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
18 changed files with 257 additions and 233 deletions

View file

@ -3,6 +3,7 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
use app_units::Au;
use atomic_refcell::AtomicRefCell;
use base::print_tree::PrintTree;
use serde::Serialize;
use servo_arc::Arc as ServoArc;
@ -13,7 +14,6 @@ use style::properties::ComputedValues;
use style::Zero;
use super::{BaseFragment, BaseFragmentInfo, CollapsedBlockMargins, Fragment};
use crate::cell::ArcRefCell;
use crate::formatting_contexts::Baselines;
use crate::fragment_tree::FragmentFlags;
use crate::geom::{
@ -53,7 +53,7 @@ pub(crate) struct BoxFragment {
#[serde(skip_serializing)]
pub style: ServoArc<ComputedValues>,
pub children: Vec<ArcRefCell<Fragment>>,
pub children: Vec<Fragment>,
/// The content rect of this fragment in the parent fragment's content rectangle. This
/// does not include padding, border, or margin -- it only includes content.
@ -84,7 +84,8 @@ pub(crate) struct BoxFragment {
/// The resolved box insets if this box is `position: sticky`. These are calculated
/// during stacking context tree construction because they rely on the size of the
/// scroll container.
pub(crate) resolved_sticky_insets: Option<PhysicalSides<AuOrAuto>>,
#[serde(skip_serializing)]
pub(crate) resolved_sticky_insets: AtomicRefCell<Option<PhysicalSides<AuOrAuto>>>,
#[serde(skip_serializing)]
pub background_mode: BackgroundMode,
@ -115,7 +116,7 @@ impl BoxFragment {
BoxFragment {
base: base_fragment_info.into(),
style,
children: children.into_iter().map(ArcRefCell::new).collect(),
children,
content_rect,
padding,
border,
@ -124,7 +125,7 @@ impl BoxFragment {
baselines: Baselines::default(),
block_margins_collapsed_with_children,
scrollable_overflow_from_children,
resolved_sticky_insets: None,
resolved_sticky_insets: AtomicRefCell::default(),
background_mode: BackgroundMode::Normal,
detailed_layout_info: None,
}
@ -234,7 +235,7 @@ impl BoxFragment {
));
for child in &self.children {
child.borrow().print(tree);
child.print(tree);
}
tree.end_level();
}
@ -278,7 +279,7 @@ impl BoxFragment {
"Should not call this method on statically positioned box."
);
if let Some(resolved_sticky_insets) = self.resolved_sticky_insets {
if let Some(resolved_sticky_insets) = *self.resolved_sticky_insets.borrow() {
return resolved_sticky_insets;
}