From 663e4507ea3c609049e4e55b2d229a877367faf7 Mon Sep 17 00:00:00 2001 From: Shannon Booth Date: Wed, 19 Jul 2023 19:44:10 +1200 Subject: [PATCH] LibJS: Deduplicate scoped continue & break bytecode generation The only two differences between these two functions are the name of the block that is created and the specific jump/break handling per boundary. --- .../Libraries/LibJS/Bytecode/Generator.cpp | 56 +++++++------------ Userland/Libraries/LibJS/Bytecode/Generator.h | 6 ++ 2 files changed, 26 insertions(+), 36 deletions(-) diff --git a/Userland/Libraries/LibJS/Bytecode/Generator.cpp b/Userland/Libraries/LibJS/Bytecode/Generator.cpp index 33cc703f4b..3f9e263992 100644 --- a/Userland/Libraries/LibJS/Bytecode/Generator.cpp +++ b/Userland/Libraries/LibJS/Bytecode/Generator.cpp @@ -377,17 +377,25 @@ void Generator::emit_set_variable(JS::Identifier const& identifier, Bytecode::Op } } -void Generator::generate_break() +void Generator::generate_scoped_jump(JumpType type) { bool last_was_finally = false; - // FIXME: Reduce code duplication for (size_t i = m_boundaries.size(); i > 0; --i) { auto boundary = m_boundaries[i - 1]; using enum BlockBoundaryType; switch (boundary) { case Break: - emit().set_targets(nearest_breakable_scope(), {}); - return; + if (type == JumpType::Break) { + emit().set_targets(nearest_breakable_scope(), {}); + return; + } + break; + case Continue: + if (type == JumpType::Continue) { + emit().set_targets(nearest_continuable_scope(), {}); + return; + } + break; case Unwind: if (!last_was_finally) emit(); @@ -396,10 +404,9 @@ void Generator::generate_break() case LeaveLexicalEnvironment: emit(); break; - case Continue: - break; case ReturnToFinally: { - auto& block = make_block(DeprecatedString::formatted("{}.break", current_block().name())); + auto jump_type_name = type == JumpType::Break ? "break"sv : "continue"sv; + auto& block = make_block(DeprecatedString::formatted("{}.{}", current_block().name(), jump_type_name)); emit(Label { block }); switch_to_basic_block(block); last_was_finally = true; @@ -410,6 +417,11 @@ void Generator::generate_break() VERIFY_NOT_REACHED(); } +void Generator::generate_break() +{ + generate_scoped_jump(JumpType::Break); +} + void Generator::generate_break(DeprecatedFlyString const& break_label) { size_t current_boundary = m_boundaries.size(); @@ -447,35 +459,7 @@ void Generator::generate_break(DeprecatedFlyString const& break_label) void Generator::generate_continue() { - bool last_was_finally = false; - // FIXME: Reduce code duplication - for (size_t i = m_boundaries.size(); i > 0; --i) { - auto boundary = m_boundaries[i - 1]; - using enum BlockBoundaryType; - switch (boundary) { - case Continue: - emit().set_targets(nearest_continuable_scope(), {}); - return; - case Unwind: - if (!last_was_finally) - emit(); - last_was_finally = false; - break; - case LeaveLexicalEnvironment: - emit(); - break; - case Break: - break; - case ReturnToFinally: { - auto& block = make_block(DeprecatedString::formatted("{}.continue", current_block().name())); - emit(Label { block }); - switch_to_basic_block(block); - last_was_finally = true; - break; - }; - } - } - VERIFY_NOT_REACHED(); + generate_scoped_jump(JumpType::Continue); } void Generator::generate_continue(DeprecatedFlyString const& continue_label) diff --git a/Userland/Libraries/LibJS/Bytecode/Generator.h b/Userland/Libraries/LibJS/Bytecode/Generator.h index c7b60b6fed..790054dc6c 100644 --- a/Userland/Libraries/LibJS/Bytecode/Generator.h +++ b/Userland/Libraries/LibJS/Bytecode/Generator.h @@ -212,6 +212,12 @@ public: [[nodiscard]] size_t next_global_variable_cache() { return m_next_global_variable_cache++; } private: + enum class JumpType { + Continue, + Break, + }; + void generate_scoped_jump(JumpType); + Generator(); ~Generator() = default;