layout: Add BoxFragment rare data (#38325)

Introduce `BoxFragmentRareData`, rare data for `BoxFragment`, which
would store the specific data that is relevant to several fragments.
This would reduce the `BoxFragment` size to 256 from 264 and add 8 bytes
for fragment that have rare data (due to the additional pointer to the
rare data).

Testing: Existing WPT coverage

Signed-off-by: Jo Steven Novaryo <jo.steven.novaryo@huawei.com>
This commit is contained in:
Jo Steven Novaryo 2025-08-01 13:17:39 +08:00 committed by GitHub
parent 09f0e20e29
commit a8886c1222
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 32 additions and 8 deletions

View file

@ -68,6 +68,24 @@ pub(crate) struct BlockLevelLayoutInfo {
pub block_margins_collapsed_with_children: CollapsedBlockMargins,
}
#[derive(MallocSizeOf)]
pub(crate) struct BoxFragmentRareData {
/// Information that is specific to a layout system (e.g., grid, table, etc.).
pub specific_layout_info: Option<SpecificLayoutInfo>,
}
impl BoxFragmentRareData {
/// Create a new rare data based on information given to the fragment. Ideally, We should
/// avoid creating rare data as much as possible to reduce the memory cost.
fn try_boxed_from(specific_layout_info: Option<SpecificLayoutInfo>) -> Option<Box<Self>> {
specific_layout_info.map(|info| {
Box::new(BoxFragmentRareData {
specific_layout_info: Some(info),
})
})
}
}
#[derive(MallocSizeOf)]
pub(crate) struct BoxFragment {
pub base: BaseFragment,
@ -105,8 +123,8 @@ pub(crate) struct BoxFragment {
pub background_mode: BackgroundMode,
/// Additional information of from layout that could be used by Javascripts and devtools.
pub specific_layout_info: Option<SpecificLayoutInfo>,
/// Rare data that not all kinds of [`BoxFragment`] would have.
pub rare_data: Option<Box<BoxFragmentRareData>>,
/// Additional information for block-level boxes.
pub block_level_layout_info: Option<Box<BlockLevelLayoutInfo>>,
@ -130,6 +148,8 @@ impl BoxFragment {
margin: PhysicalSides<Au>,
specific_layout_info: Option<SpecificLayoutInfo>,
) -> BoxFragment {
let rare_data = BoxFragmentRareData::try_boxed_from(specific_layout_info);
BoxFragment {
base: base_fragment_info.into(),
style,
@ -143,7 +163,7 @@ impl BoxFragment {
scrollable_overflow: None,
resolved_sticky_insets: AtomicRefCell::default(),
background_mode: BackgroundMode::Normal,
specific_layout_info,
rare_data,
block_level_layout_info: None,
spatial_tree_node: AtomicRefCell::default(),
}
@ -198,6 +218,10 @@ impl BoxFragment {
self.background_mode = BackgroundMode::None;
}
pub fn specific_layout_info(&self) -> Option<&SpecificLayoutInfo> {
self.rare_data.as_ref()?.specific_layout_info.as_ref()
}
pub fn with_block_level_layout_info(
mut self,
block_margins_collapsed_with_children: CollapsedBlockMargins,
@ -512,13 +536,13 @@ impl BoxFragment {
/// <https://www.w3.org/TR/css-tables-3/#table-wrapper-box>
pub(crate) fn is_table_wrapper(&self) -> bool {
matches!(
self.specific_layout_info,
self.specific_layout_info(),
Some(SpecificLayoutInfo::TableWrapper)
)
}
pub(crate) fn has_collapsed_borders(&self) -> bool {
match &self.specific_layout_info {
match self.specific_layout_info() {
Some(SpecificLayoutInfo::TableCellWithCollapsedBorders) => true,
Some(SpecificLayoutInfo::TableGridWithCollapsedBorders(_)) => true,
Some(SpecificLayoutInfo::TableWrapper) => {