diff --git a/Userland/Libraries/LibJS/Bytecode/Generator.cpp b/Userland/Libraries/LibJS/Bytecode/Generator.cpp index 3f9e263992..bd3aca468e 100644 --- a/Userland/Libraries/LibJS/Bytecode/Generator.cpp +++ b/Userland/Libraries/LibJS/Bytecode/Generator.cpp @@ -417,16 +417,14 @@ void Generator::generate_scoped_jump(JumpType type) VERIFY_NOT_REACHED(); } -void Generator::generate_break() -{ - generate_scoped_jump(JumpType::Break); -} - -void Generator::generate_break(DeprecatedFlyString const& break_label) +void Generator::generate_labelled_jump(JumpType type, DeprecatedFlyString const& label) { size_t current_boundary = m_boundaries.size(); bool last_was_finally = false; - for (auto const& breakable_scope : m_breakable_scopes.in_reverse()) { + + auto const& jumpable_scopes = type == JumpType::Continue ? m_continuable_scopes : m_breakable_scopes; + + for (auto const& jumpable_scope : jumpable_scopes.in_reverse()) { for (; current_boundary > 0; --current_boundary) { auto boundary = m_boundaries[current_boundary - 1]; if (boundary == BlockBoundaryType::Unwind) { @@ -436,27 +434,38 @@ void Generator::generate_break(DeprecatedFlyString const& break_label) } else if (boundary == BlockBoundaryType::LeaveLexicalEnvironment) { emit(); } else if (boundary == BlockBoundaryType::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; - } else if (boundary == BlockBoundaryType::Break) { - // Make sure we don't process this boundary twice if the current breakable scope doesn't contain the target label. + } else if ((type == JumpType::Continue && boundary == BlockBoundaryType::Continue) || (type == JumpType::Break && boundary == BlockBoundaryType::Break)) { + // Make sure we don't process this boundary twice if the current jumpable scope doesn't contain the target label. --current_boundary; break; } } - if (breakable_scope.language_label_set.contains_slow(break_label)) { - emit().set_targets(breakable_scope.bytecode_target, {}); + if (jumpable_scope.language_label_set.contains_slow(label)) { + emit().set_targets(jumpable_scope.bytecode_target, {}); return; } } - // We must have a breakable scope available that contains the label, as this should be enforced by the parser. + // We must have a jumpable scope available that contains the label, as this should be enforced by the parser. VERIFY_NOT_REACHED(); } +void Generator::generate_break() +{ + generate_scoped_jump(JumpType::Break); +} + +void Generator::generate_break(DeprecatedFlyString const& break_label) +{ + generate_labelled_jump(JumpType::Break, break_label); +} + void Generator::generate_continue() { generate_scoped_jump(JumpType::Continue); @@ -464,37 +473,7 @@ void Generator::generate_continue() void Generator::generate_continue(DeprecatedFlyString const& continue_label) { - size_t current_boundary = m_boundaries.size(); - bool last_was_finally = false; - for (auto const& continuable_scope : m_continuable_scopes.in_reverse()) { - for (; current_boundary > 0; --current_boundary) { - auto boundary = m_boundaries[current_boundary - 1]; - if (boundary == BlockBoundaryType::Unwind) { - if (!last_was_finally) - emit(); - last_was_finally = false; - } else if (boundary == BlockBoundaryType::LeaveLexicalEnvironment) { - emit(); - } else if (boundary == BlockBoundaryType::ReturnToFinally) { - auto& block = make_block(DeprecatedString::formatted("{}.continue", current_block().name())); - emit(Label { block }); - switch_to_basic_block(block); - last_was_finally = true; - } else if (boundary == BlockBoundaryType::Continue) { - // Make sure we don't process this boundary twice if the current continuable scope doesn't contain the target label. - --current_boundary; - break; - } - } - - if (continuable_scope.language_label_set.contains_slow(continue_label)) { - emit().set_targets(continuable_scope.bytecode_target, {}); - return; - } - } - - // We must have a continuable scope available that contains the label, as this should be enforced by the parser. - VERIFY_NOT_REACHED(); + generate_labelled_jump(JumpType::Continue, continue_label); } void Generator::push_home_object(Register register_) diff --git a/Userland/Libraries/LibJS/Bytecode/Generator.h b/Userland/Libraries/LibJS/Bytecode/Generator.h index 790054dc6c..b759a8a2bb 100644 --- a/Userland/Libraries/LibJS/Bytecode/Generator.h +++ b/Userland/Libraries/LibJS/Bytecode/Generator.h @@ -217,6 +217,7 @@ private: Break, }; void generate_scoped_jump(JumpType); + void generate_labelled_jump(JumpType, DeprecatedFlyString const& label); Generator(); ~Generator() = default;