LibWeb: Make CSS::is_inherited_property(PropertyID) go fast

Instead of switching on the PropertyID and doing a boatload of
comparisons, we reorder the PropertyID enum so that all inherited
properties are in two contiguous ranges (one for shorthands,
one for longhands).

This replaces the switch statement with two simple range checks.

Note that the property order change is observable via
window.getComputedStyle(), but the order of those properties is
implementation defined anyway.

Removes a 1.5% item from the profile when loading https://hemnet.se/
This commit is contained in:
Andreas Kling
2024-09-03 17:48:43 +02:00
committed by Andreas Kling
parent 0fab3d3b62
commit 1f5c49f40d
2 changed files with 93 additions and 98 deletions

View File

@@ -136,46 +136,61 @@ enum class PropertyID {
All,
)~~~");
Vector<ByteString> shorthand_property_ids;
Vector<ByteString> longhand_property_ids;
Vector<ByteString> inherited_shorthand_property_ids;
Vector<ByteString> inherited_longhand_property_ids;
Vector<ByteString> noninherited_shorthand_property_ids;
Vector<ByteString> noninherited_longhand_property_ids;
properties.for_each_member([&](auto& name, auto& value) {
VERIFY(value.is_object());
if (value.as_object().has("longhands"sv))
shorthand_property_ids.append(name);
else
longhand_property_ids.append(name);
bool inherited = value.as_object().get_bool("inherited"sv).value_or(false);
if (value.as_object().has("longhands"sv)) {
if (inherited)
inherited_shorthand_property_ids.append(name);
else
noninherited_shorthand_property_ids.append(name);
} else {
if (inherited)
inherited_longhand_property_ids.append(name);
else
noninherited_longhand_property_ids.append(name);
}
});
auto first_property_id = shorthand_property_ids.first();
auto last_property_id = longhand_property_ids.last();
// Section order:
// 1. inherited shorthand properties
// 2. noninherited shorthand properties
// 3. inherited longhand properties
// 4. noninherited longhand properties
for (auto& name : shorthand_property_ids) {
auto member_generator = generator.fork();
member_generator.set("name:titlecase", title_casify(name));
auto first_property_id = inherited_shorthand_property_ids.first();
auto last_property_id = noninherited_longhand_property_ids.last();
member_generator.append(R"~~~(
@name:titlecase@,
auto emit_properties = [&](auto& property_ids) {
for (auto& name : property_ids) {
auto member_generator = generator.fork();
member_generator.set("name:titlecase", title_casify(name));
member_generator.append(R"~~~(
@name:titlecase@,
)~~~");
}
}
};
for (auto& name : longhand_property_ids) {
auto member_generator = generator.fork();
member_generator.set("name:titlecase", title_casify(name));
member_generator.append(R"~~~(
@name:titlecase@,
)~~~");
}
emit_properties(inherited_shorthand_property_ids);
emit_properties(noninherited_shorthand_property_ids);
emit_properties(inherited_longhand_property_ids);
emit_properties(noninherited_longhand_property_ids);
generator.set("first_property_id", title_casify(first_property_id));
generator.set("last_property_id", title_casify(last_property_id));
generator.set("first_shorthand_property_id", title_casify(shorthand_property_ids.first()));
generator.set("last_shorthand_property_id", title_casify(shorthand_property_ids.last()));
generator.set("first_longhand_property_id", title_casify(inherited_longhand_property_ids.first()));
generator.set("last_longhand_property_id", title_casify(noninherited_longhand_property_ids.last()));
generator.set("first_longhand_property_id", title_casify(longhand_property_ids.first()));
generator.set("last_longhand_property_id", title_casify(longhand_property_ids.last()));
generator.set("first_inherited_shorthand_property_id", title_casify(inherited_shorthand_property_ids.first()));
generator.set("last_inherited_shorthand_property_id", title_casify(inherited_shorthand_property_ids.last()));
generator.set("first_inherited_longhand_property_id", title_casify(inherited_longhand_property_ids.first()));
generator.set("last_inherited_longhand_property_id", title_casify(inherited_longhand_property_ids.last()));
generator.append(R"~~~(
};
@@ -247,8 +262,10 @@ bool property_affects_stacking_context(PropertyID);
constexpr PropertyID first_property_id = PropertyID::@first_property_id@;
constexpr PropertyID last_property_id = PropertyID::@last_property_id@;
constexpr PropertyID first_shorthand_property_id = PropertyID::@first_shorthand_property_id@;
constexpr PropertyID last_shorthand_property_id = PropertyID::@last_shorthand_property_id@;
constexpr PropertyID first_inherited_shorthand_property_id = PropertyID::@first_inherited_shorthand_property_id@;
constexpr PropertyID last_inherited_shorthand_property_id = PropertyID::@last_inherited_shorthand_property_id@;
constexpr PropertyID first_inherited_longhand_property_id = PropertyID::@first_inherited_longhand_property_id@;
constexpr PropertyID last_inherited_longhand_property_id = PropertyID::@last_inherited_longhand_property_id@;
constexpr PropertyID first_longhand_property_id = PropertyID::@first_longhand_property_id@;
constexpr PropertyID last_longhand_property_id = PropertyID::@last_longhand_property_id@;
@@ -543,33 +560,11 @@ bool is_animatable_property(PropertyID property_id)
bool is_inherited_property(PropertyID property_id)
{
switch (property_id) {
)~~~");
properties.for_each_member([&](auto& name, auto& value) {
VERIFY(value.is_object());
bool inherited = false;
if (value.as_object().has("inherited"sv)) {
auto inherited_value = value.as_object().get_bool("inherited"sv);
VERIFY(inherited_value.has_value());
inherited = inherited_value.value();
}
if (inherited) {
auto member_generator = generator.fork();
member_generator.set("name:titlecase", title_casify(name));
member_generator.append(R"~~~(
case PropertyID::@name:titlecase@:
if (property_id >= first_inherited_shorthand_property_id && property_id <= last_inherited_longhand_property_id)
return true;
)~~~");
}
});
generator.append(R"~~~(
default:
return false;
}
if (property_id >= first_inherited_longhand_property_id && property_id <= last_inherited_longhand_property_id)
return true;
return false;
}
bool property_affects_layout(PropertyID property_id)