mirror of
https://github.com/RGBCube/serenity
synced 2025-07-23 09:27:35 +00:00
LibJS/Bytecode: Unwind environments before block terminating instruction
When we reach a block terminating instruction (e.g. Break, Throw), we cannot generate anymore instructions after it. This would not allow us to leave any lexical/variable environments. This uses the mechanism introduced in ba9c49 to unwind environments when we encounter these instructions.
This commit is contained in:
parent
ada8880f58
commit
858bcac4c7
2 changed files with 36 additions and 20 deletions
|
@ -76,6 +76,33 @@ Label Generator::nearest_continuable_scope() const
|
||||||
return m_continuable_scopes.last();
|
return m_continuable_scopes.last();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Generator::begin_variable_scope(BindingMode mode, SurroundingScopeKind kind)
|
||||||
|
{
|
||||||
|
m_variable_scopes.append({ kind, mode, {} });
|
||||||
|
if (mode != BindingMode::Global) {
|
||||||
|
start_boundary(mode == BindingMode::Lexical ? BlockBoundaryType::LeaveLexicalEnvironment : BlockBoundaryType::LeaveVariableEnvironment);
|
||||||
|
emit<Bytecode::Op::CreateEnvironment>(
|
||||||
|
mode == BindingMode::Lexical
|
||||||
|
? Bytecode::Op::EnvironmentMode::Lexical
|
||||||
|
: Bytecode::Op::EnvironmentMode::Var);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Generator::end_variable_scope()
|
||||||
|
{
|
||||||
|
auto mode = m_variable_scopes.take_last().mode;
|
||||||
|
if (mode != BindingMode::Global) {
|
||||||
|
end_boundary(mode == BindingMode::Lexical ? BlockBoundaryType::LeaveLexicalEnvironment : BlockBoundaryType::LeaveVariableEnvironment);
|
||||||
|
|
||||||
|
if (!m_current_basic_block->is_terminated()) {
|
||||||
|
emit<Bytecode::Op::LeaveEnvironment>(
|
||||||
|
mode == BindingMode::Lexical
|
||||||
|
? Bytecode::Op::EnvironmentMode::Lexical
|
||||||
|
: Bytecode::Op::EnvironmentMode::Var);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Generator::begin_continuable_scope(Label continue_target)
|
void Generator::begin_continuable_scope(Label continue_target)
|
||||||
{
|
{
|
||||||
m_continuable_scopes.append(continue_target);
|
m_continuable_scopes.append(continue_target);
|
||||||
|
|
|
@ -150,31 +150,16 @@ public:
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
void begin_variable_scope(BindingMode mode = BindingMode::Lexical, SurroundingScopeKind kind = SurroundingScopeKind::Block)
|
|
||||||
{
|
void begin_variable_scope(BindingMode mode = BindingMode::Lexical, SurroundingScopeKind kind = SurroundingScopeKind::Block);
|
||||||
m_variable_scopes.append({ kind, mode, {} });
|
void end_variable_scope();
|
||||||
if (mode != BindingMode::Global) {
|
|
||||||
emit<Bytecode::Op::CreateEnvironment>(
|
|
||||||
mode == BindingMode::Lexical
|
|
||||||
? Bytecode::Op::EnvironmentMode::Lexical
|
|
||||||
: Bytecode::Op::EnvironmentMode::Var);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void end_variable_scope()
|
|
||||||
{
|
|
||||||
auto mode = m_variable_scopes.take_last().mode;
|
|
||||||
if (mode != BindingMode::Global && !m_current_basic_block->is_terminated()) {
|
|
||||||
emit<Bytecode::Op::LeaveEnvironment>(
|
|
||||||
mode == BindingMode::Lexical
|
|
||||||
? Bytecode::Op::EnvironmentMode::Lexical
|
|
||||||
: Bytecode::Op::EnvironmentMode::Var);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
enum class BlockBoundaryType {
|
enum class BlockBoundaryType {
|
||||||
Break,
|
Break,
|
||||||
Continue,
|
Continue,
|
||||||
Unwind,
|
Unwind,
|
||||||
|
LeaveLexicalEnvironment,
|
||||||
|
LeaveVariableEnvironment,
|
||||||
};
|
};
|
||||||
template<typename OpType>
|
template<typename OpType>
|
||||||
void perform_needed_unwinds(bool is_break_node = false) requires(OpType::IsTerminator)
|
void perform_needed_unwinds(bool is_break_node = false) requires(OpType::IsTerminator)
|
||||||
|
@ -191,6 +176,10 @@ public:
|
||||||
break;
|
break;
|
||||||
if (boundary == BlockBoundaryType::Unwind)
|
if (boundary == BlockBoundaryType::Unwind)
|
||||||
emit<Bytecode::Op::LeaveUnwindContext>();
|
emit<Bytecode::Op::LeaveUnwindContext>();
|
||||||
|
else if (boundary == BlockBoundaryType::LeaveLexicalEnvironment)
|
||||||
|
emit<Bytecode::Op::LeaveEnvironment>(Bytecode::Op::EnvironmentMode::Lexical);
|
||||||
|
else if (boundary == BlockBoundaryType::LeaveVariableEnvironment)
|
||||||
|
emit<Bytecode::Op::LeaveEnvironment>(Bytecode::Op::EnvironmentMode::Var);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue