From b96118b5d1975e82aa573b322d975ef165671b1f Mon Sep 17 00:00:00 2001 From: Ali Mohammad Pur Date: Wed, 10 Nov 2021 22:22:26 +0330 Subject: [PATCH] LibJS: Fix codegen for nodes after try statements without 'finally' Previously we were just dropping them on the ground :P --- .../Libraries/LibJS/Bytecode/ASTCodegen.cpp | 11 +++++++++-- Userland/Libraries/LibJS/Bytecode/Instruction.h | 1 + Userland/Libraries/LibJS/Bytecode/Op.cpp | 17 +++++++++++++++++ Userland/Libraries/LibJS/Bytecode/Op.h | 16 ++++++++++++++++ 4 files changed, 43 insertions(+), 2 deletions(-) diff --git a/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp b/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp index f7a59926c5..2f4d6a3b6d 100644 --- a/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp +++ b/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp @@ -1189,8 +1189,15 @@ void TryStatement::generate_bytecode(Bytecode::Generator& generator) const generator.switch_to_basic_block(target_block); m_block->generate_bytecode(generator); - if (m_finalizer && !generator.is_current_block_terminated()) - generator.emit(finalizer_target); + if (!generator.is_current_block_terminated()) { + if (m_finalizer) { + generator.emit(finalizer_target); + } else { + auto& block = generator.make_block(); + generator.emit(Bytecode::Label { block }); + next_block = █ + } + } generator.switch_to_basic_block(next_block ? *next_block : saved_block); } diff --git a/Userland/Libraries/LibJS/Bytecode/Instruction.h b/Userland/Libraries/LibJS/Bytecode/Instruction.h index 941a990b40..d9da87b4d1 100644 --- a/Userland/Libraries/LibJS/Bytecode/Instruction.h +++ b/Userland/Libraries/LibJS/Bytecode/Instruction.h @@ -24,6 +24,7 @@ O(Div) \ O(EnterUnwindContext) \ O(Exp) \ + O(FinishUnwind) \ O(GetById) \ O(GetByValue) \ O(GetIterator) \ diff --git a/Userland/Libraries/LibJS/Bytecode/Op.cpp b/Userland/Libraries/LibJS/Bytecode/Op.cpp index 32655dfe74..b2ea9b97f7 100644 --- a/Userland/Libraries/LibJS/Bytecode/Op.cpp +++ b/Userland/Libraries/LibJS/Bytecode/Op.cpp @@ -446,6 +446,18 @@ void EnterUnwindContext::replace_references_impl(BasicBlock const& from, BasicBl m_finalizer_target = Label { to }; } +void FinishUnwind::execute_impl(Bytecode::Interpreter& interpreter) const +{ + interpreter.leave_unwind_context(); + interpreter.jump(m_next_target); +} + +void FinishUnwind::replace_references_impl(BasicBlock const& from, BasicBlock const& to) +{ + if (&m_next_target.block() == &from) + m_next_target = Label { to }; +} + void LeaveUnwindContext::execute_impl(Bytecode::Interpreter& interpreter) const { interpreter.leave_unwind_context(); @@ -751,6 +763,11 @@ String EnterUnwindContext::to_string_impl(Bytecode::Executable const&) const return String::formatted("EnterUnwindContext handler:{} finalizer:{} entry:{}", handler_string, finalizer_string, m_entry_point); } +String FinishUnwind::to_string_impl(const Bytecode::Executable&) const +{ + return String::formatted("FinishUnwind next:{}", m_next_target); +} + String LeaveUnwindContext::to_string_impl(Bytecode::Executable const&) const { return "LeaveUnwindContext"; diff --git a/Userland/Libraries/LibJS/Bytecode/Op.h b/Userland/Libraries/LibJS/Bytecode/Op.h index 7043f6617c..ad848d7cc9 100644 --- a/Userland/Libraries/LibJS/Bytecode/Op.h +++ b/Userland/Libraries/LibJS/Bytecode/Op.h @@ -610,6 +610,22 @@ public: void replace_references_impl(BasicBlock const&, BasicBlock const&) { } }; +class FinishUnwind final : public Instruction { +public: + FinishUnwind(Label next) + : Instruction(Type::FinishUnwind) + , m_next_target(move(next)) + { + } + + void execute_impl(Bytecode::Interpreter&) const; + String to_string_impl(Bytecode::Executable const&) const; + void replace_references_impl(BasicBlock const&, BasicBlock const&); + +private: + Label m_next_target; +}; + class ContinuePendingUnwind final : public Instruction { public: constexpr static bool IsTerminator = true;