LibWeb: Use bitmaps for important/inherited bits in StyleProperties

This avoids padding the style value array, shrinking StyleProperties
from 4368 bytes to 2288 bytes per instance.
This commit is contained in:
Andreas Kling 2024-08-02 13:59:19 +02:00 committed by Andreas Kling
commit b42b7c8dd0
Notes: github-actions[bot] 2024-08-02 18:38:41 +00:00
5 changed files with 122 additions and 74 deletions

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018-2023, Andreas Kling <kling@serenityos.org>
* Copyright (c) 2018-2024, Andreas Kling <andreas@ladybird.org>
* Copyright (c) 2021-2024, Sam Atkins <atkinssj@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
@ -37,19 +37,55 @@
namespace Web::CSS {
NonnullRefPtr<StyleProperties> StyleProperties::clone() const
{
auto clone = adopt_ref(*new StyleProperties);
clone->m_property_values = m_property_values;
clone->m_animated_property_values = m_animated_property_values;
clone->m_property_important = m_property_important;
clone->m_property_inherited = m_property_inherited;
clone->m_font_list = m_font_list;
clone->m_line_height = m_line_height;
clone->m_animation_name_source = m_animation_name_source;
clone->m_math_depth = m_math_depth;
return clone;
}
bool StyleProperties::is_property_important(CSS::PropertyID property_id) const
{
return m_property_values[to_underlying(property_id)].style && m_property_values[to_underlying(property_id)].important == Important::Yes;
size_t n = to_underlying(property_id);
return m_property_important[n / 8] & (1 << (n % 8));
}
void StyleProperties::set_property_important(CSS::PropertyID property_id, Important important)
{
size_t n = to_underlying(property_id);
if (important == Important::Yes)
m_property_important[n / 8] |= (1 << (n % 8));
else
m_property_important[n / 8] &= ~(1 << (n % 8));
}
bool StyleProperties::is_property_inherited(CSS::PropertyID property_id) const
{
return m_property_values[to_underlying(property_id)].style && m_property_values[to_underlying(property_id)].inherited == Inherited::Yes;
size_t n = to_underlying(property_id);
return m_property_inherited[n / 8] & (1 << (n % 8));
}
void StyleProperties::set_property_inherited(CSS::PropertyID property_id, Inherited inherited)
{
size_t n = to_underlying(property_id);
if (inherited == Inherited::Yes)
m_property_inherited[n / 8] |= (1 << (n % 8));
else
m_property_inherited[n / 8] &= ~(1 << (n % 8));
}
void StyleProperties::set_property(CSS::PropertyID id, NonnullRefPtr<StyleValue const> value, Inherited inherited, Important important)
{
m_property_values[to_underlying(id)] = StyleValueAndMetadata { move(value), important, inherited };
m_property_values[to_underlying(id)] = move(value);
set_property_important(id, important);
set_property_inherited(id, inherited);
}
void StyleProperties::set_animated_property(CSS::PropertyID id, NonnullRefPtr<StyleValue const> value)
@ -68,14 +104,14 @@ NonnullRefPtr<StyleValue const> StyleProperties::property(CSS::PropertyID proper
return *animated_value;
// By the time we call this method, all properties have values assigned.
return *m_property_values[to_underlying(property_id)].style;
return *m_property_values[to_underlying(property_id)];
}
RefPtr<StyleValue const> StyleProperties::maybe_null_property(CSS::PropertyID property_id) const
{
if (auto animated_value = m_animated_property_values.get(property_id).value_or(nullptr))
return *animated_value;
return m_property_values[to_underlying(property_id)].style;
return m_property_values[to_underlying(property_id)];
}
CSS::Size StyleProperties::size_value(CSS::PropertyID id) const
@ -571,15 +607,15 @@ bool StyleProperties::operator==(StyleProperties const& other) const
for (size_t i = 0; i < m_property_values.size(); ++i) {
auto const& my_style = m_property_values[i];
auto const& other_style = other.m_property_values[i];
if (!my_style.style) {
if (other_style.style)
if (!my_style) {
if (other_style)
return false;
continue;
}
if (!other_style.style)
if (!other_style)
return false;
auto const& my_value = *my_style.style;
auto const& other_value = *other_style.style;
auto const& my_value = *my_style;
auto const& other_value = *other_style;
if (my_value.type() != other_value.type())
return false;
if (my_value != other_value)