mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 22:18:12 +00:00
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.
This commit is contained in:
parent
c4bad2186f
commit
663e4507ea
2 changed files with 26 additions and 36 deletions
|
@ -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;
|
bool last_was_finally = false;
|
||||||
// FIXME: Reduce code duplication
|
|
||||||
for (size_t i = m_boundaries.size(); i > 0; --i) {
|
for (size_t i = m_boundaries.size(); i > 0; --i) {
|
||||||
auto boundary = m_boundaries[i - 1];
|
auto boundary = m_boundaries[i - 1];
|
||||||
using enum BlockBoundaryType;
|
using enum BlockBoundaryType;
|
||||||
switch (boundary) {
|
switch (boundary) {
|
||||||
case Break:
|
case Break:
|
||||||
emit<Op::Jump>().set_targets(nearest_breakable_scope(), {});
|
if (type == JumpType::Break) {
|
||||||
return;
|
emit<Op::Jump>().set_targets(nearest_breakable_scope(), {});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Continue:
|
||||||
|
if (type == JumpType::Continue) {
|
||||||
|
emit<Op::Jump>().set_targets(nearest_continuable_scope(), {});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case Unwind:
|
case Unwind:
|
||||||
if (!last_was_finally)
|
if (!last_was_finally)
|
||||||
emit<Bytecode::Op::LeaveUnwindContext>();
|
emit<Bytecode::Op::LeaveUnwindContext>();
|
||||||
|
@ -396,10 +404,9 @@ void Generator::generate_break()
|
||||||
case LeaveLexicalEnvironment:
|
case LeaveLexicalEnvironment:
|
||||||
emit<Bytecode::Op::LeaveLexicalEnvironment>();
|
emit<Bytecode::Op::LeaveLexicalEnvironment>();
|
||||||
break;
|
break;
|
||||||
case Continue:
|
|
||||||
break;
|
|
||||||
case ReturnToFinally: {
|
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<Op::ScheduleJump>(Label { block });
|
emit<Op::ScheduleJump>(Label { block });
|
||||||
switch_to_basic_block(block);
|
switch_to_basic_block(block);
|
||||||
last_was_finally = true;
|
last_was_finally = true;
|
||||||
|
@ -410,6 +417,11 @@ void Generator::generate_break()
|
||||||
VERIFY_NOT_REACHED();
|
VERIFY_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Generator::generate_break()
|
||||||
|
{
|
||||||
|
generate_scoped_jump(JumpType::Break);
|
||||||
|
}
|
||||||
|
|
||||||
void Generator::generate_break(DeprecatedFlyString const& break_label)
|
void Generator::generate_break(DeprecatedFlyString const& break_label)
|
||||||
{
|
{
|
||||||
size_t current_boundary = m_boundaries.size();
|
size_t current_boundary = m_boundaries.size();
|
||||||
|
@ -447,35 +459,7 @@ void Generator::generate_break(DeprecatedFlyString const& break_label)
|
||||||
|
|
||||||
void Generator::generate_continue()
|
void Generator::generate_continue()
|
||||||
{
|
{
|
||||||
bool last_was_finally = false;
|
generate_scoped_jump(JumpType::Continue);
|
||||||
// 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<Op::Jump>().set_targets(nearest_continuable_scope(), {});
|
|
||||||
return;
|
|
||||||
case Unwind:
|
|
||||||
if (!last_was_finally)
|
|
||||||
emit<Bytecode::Op::LeaveUnwindContext>();
|
|
||||||
last_was_finally = false;
|
|
||||||
break;
|
|
||||||
case LeaveLexicalEnvironment:
|
|
||||||
emit<Bytecode::Op::LeaveLexicalEnvironment>();
|
|
||||||
break;
|
|
||||||
case Break:
|
|
||||||
break;
|
|
||||||
case ReturnToFinally: {
|
|
||||||
auto& block = make_block(DeprecatedString::formatted("{}.continue", current_block().name()));
|
|
||||||
emit<Op::ScheduleJump>(Label { block });
|
|
||||||
switch_to_basic_block(block);
|
|
||||||
last_was_finally = true;
|
|
||||||
break;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
VERIFY_NOT_REACHED();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Generator::generate_continue(DeprecatedFlyString const& continue_label)
|
void Generator::generate_continue(DeprecatedFlyString const& continue_label)
|
||||||
|
|
|
@ -212,6 +212,12 @@ public:
|
||||||
[[nodiscard]] size_t next_global_variable_cache() { return m_next_global_variable_cache++; }
|
[[nodiscard]] size_t next_global_variable_cache() { return m_next_global_variable_cache++; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
enum class JumpType {
|
||||||
|
Continue,
|
||||||
|
Break,
|
||||||
|
};
|
||||||
|
void generate_scoped_jump(JumpType);
|
||||||
|
|
||||||
Generator();
|
Generator();
|
||||||
~Generator() = default;
|
~Generator() = default;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue