From 4e406b07305007c84cef637f5753c196c34fac9c Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Sun, 6 Nov 2022 07:57:23 +0100 Subject: [PATCH] Meta+LibUnicode: Avoid relocations for emoji data Previously each emoji had its own symbol in the library which was then referred to by another symbol. This caused thousands of avoidable data relocations at load time. This saves about 122kB RAM for each process which uses LibUnicode. --- .../LibUnicode/GenerateEmojiData.cpp | 64 +++++++++++-------- 1 file changed, 39 insertions(+), 25 deletions(-) diff --git a/Meta/Lagom/Tools/CodeGenerators/LibUnicode/GenerateEmojiData.cpp b/Meta/Lagom/Tools/CodeGenerators/LibUnicode/GenerateEmojiData.cpp index c568682769..0722473ecd 100644 --- a/Meta/Lagom/Tools/CodeGenerators/LibUnicode/GenerateEmojiData.cpp +++ b/Meta/Lagom/Tools/CodeGenerators/LibUnicode/GenerateEmojiData.cpp @@ -25,9 +25,9 @@ struct Emoji { String subgroup; u32 display_order { 0 }; Vector code_points; - String code_points_name; String encoded_code_points; String status; + size_t code_point_array_index { 0 }; }; struct EmojiData { @@ -107,7 +107,6 @@ static ErrorOr parse_emoji_test_data(Core::Stream::BufferedFile& file, Emo auto name = emoji_and_name.substring_view(emoji_and_name_spaces[2]).trim_whitespace(); emoji.name = emoji_data.unique_strings.ensure(name.to_titlecase_string()); - emoji.code_points_name = String::join('_', code_points); emoji.encoded_code_points = emoji_and_name.substring_view(0, emoji_and_name_spaces[1]).trim_whitespace(); emoji.status = line.substring_view(*status_index + 1, *emoji_and_name_index - *status_index - 1).trim_whitespace(); @@ -161,7 +160,6 @@ static ErrorOr parse_emoji_serenity_data(Core::Stream::BufferedFile& file, name = name.to_titlecase(); emoji.name = emoji_data.unique_strings.ensure(move(name)); - emoji.code_points_name = String::join('_', emoji.code_points); TRY(emoji_data.emojis.try_append(move(emoji))); } @@ -199,6 +197,26 @@ namespace Unicode { emoji_data.unique_strings.generate(generator); + size_t total_code_point_count { 0 }; + for (auto const& emoji : emoji_data.emojis) { + total_code_point_count += emoji.code_points.size(); + } + generator.set("total_code_point_count", String::number(total_code_point_count)); + + generator.append(R"~~~( +static constexpr Array s_emoji_code_points { {)~~~"); + + bool first = true; + for (auto const& emoji : emoji_data.emojis) { + for (auto code_point : emoji.code_points) { + generator.append(first ? " "sv : ", "sv); + generator.append(String::formatted("{:#x}", code_point)); + first = false; + } + } + + generator.append(" } };"sv); + generator.append(R"~~~( struct EmojiData { constexpr Emoji to_unicode_emoji() const @@ -207,35 +225,24 @@ struct EmojiData { emoji.name = decode_string(name); emoji.group = static_cast(group); emoji.display_order = display_order; - emoji.code_points = code_points; + emoji.code_points = code_points(); return emoji; } + constexpr Span code_points() const + { + return Span(s_emoji_code_points.data() + code_point_start, code_point_count); + } + @string_index_type@ name { 0 }; u8 group { 0 }; u32 display_order { 0 }; - Span code_points; + size_t code_point_start { 0 }; + size_t code_point_count { 0 }; }; )~~~"); - for (auto const& emoji : emoji_data.emojis) { - generator.set("name"sv, emoji.code_points_name); - generator.set("size"sv, String::number(emoji.code_points.size())); - - generator.append(R"~~~( -static constexpr Array s_@name@ { {)~~~"); - - bool first = true; - for (auto code_point : emoji.code_points) { - generator.append(first ? " "sv : ", "sv); - generator.append(String::formatted("{:#x}", code_point)); - first = false; - } - - generator.append(" } };"sv); - } - generator.append(R"~~~( static constexpr Array s_emojis { {)~~~"); @@ -244,10 +251,11 @@ static constexpr Array s_emojis { {)~~~"); generator.set("name"sv, String::number(emoji.name)); generator.set("group"sv, String::number(to_underlying(emoji.group))); generator.set("display_order"sv, String::number(emoji.display_order)); - generator.set("code_points_name"sv, emoji.code_points_name); + generator.set("code_point_start"sv, String::number(emoji.code_point_array_index)); + generator.set("code_point_count"sv, String::number(emoji.code_points.size())); generator.append(R"~~~( - { @name@, @group@, @display_order@, s_@code_points_name@ },)~~~"); + { @name@, @group@, @display_order@, @code_point_start@, @code_point_count@ },)~~~"); } generator.append(R"~~~( @@ -256,7 +264,7 @@ static constexpr Array s_emojis { {)~~~"); Optional find_emoji_for_code_points(Span code_points) { for (auto& emoji : s_emojis) { - if (emoji.code_points == code_points) + if (emoji.code_points() == code_points) return emoji.to_unicode_emoji(); } @@ -344,6 +352,12 @@ ErrorOr serenity_main(Main::Arguments arguments) TRY(parse_emoji_serenity_data(*emoji_serenity_file, emoji_data)); } + size_t code_point_array_index { 0 }; + for (auto& emoji : emoji_data.emojis) { + emoji.code_point_array_index = code_point_array_index; + code_point_array_index += emoji.code_points.size(); + } + if (!generated_header_path.is_empty()) { auto generated_header_file = TRY(open_file(generated_header_path, Core::Stream::OpenMode::Write)); TRY(generate_emoji_data_header(*generated_header_file, emoji_data));