diff --git a/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp b/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp index 7ec551bc26..e0711f213d 100644 --- a/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp +++ b/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp @@ -2308,6 +2308,7 @@ Bytecode::CodeGenerationErrorOr TryStatement::generate_bytecode(Bytecode:: Optional handler_target; Optional finalizer_target; + Optional unwind_context; Bytecode::BasicBlock* next_block { nullptr }; @@ -2323,10 +2324,10 @@ Bytecode::CodeGenerationErrorOr TryStatement::generate_bytecode(Bytecode:: generator.emit(next_target); } finalizer_target = Bytecode::Label { finalizer_block }; - } - if (m_finalizer) generator.start_boundary(Bytecode::Generator::BlockBoundaryType::ReturnToFinally); + unwind_context.emplace(generator, finalizer_target); + } if (m_handler) { auto& handler_block = generator.make_block(); generator.switch_to_basic_block(handler_block); @@ -2374,6 +2375,7 @@ Bytecode::CodeGenerationErrorOr TryStatement::generate_bytecode(Bytecode:: generator.emit(*finalizer_target); } else { VERIFY(!next_block); + VERIFY(!unwind_context.has_value()); next_block = &generator.make_block(); auto next_target = Bytecode::Label { *next_block }; generator.emit(next_target); @@ -2382,6 +2384,11 @@ Bytecode::CodeGenerationErrorOr TryStatement::generate_bytecode(Bytecode:: } if (m_finalizer) generator.end_boundary(Bytecode::Generator::BlockBoundaryType::ReturnToFinally); + if (m_handler) { + if (!m_finalizer) + unwind_context.emplace(generator, OptionalNone()); + unwind_context->set_handler(handler_target.value()); + } auto& target_block = generator.make_block(); generator.switch_to_basic_block(saved_block); @@ -2396,6 +2403,8 @@ Bytecode::CodeGenerationErrorOr TryStatement::generate_bytecode(Bytecode:: if (m_finalizer) { generator.emit(*finalizer_target); } else { + VERIFY(unwind_context.has_value()); + unwind_context.clear(); if (!next_block) next_block = &generator.make_block(); generator.emit(); diff --git a/Userland/Libraries/LibJS/Bytecode/BasicBlock.cpp b/Userland/Libraries/LibJS/Bytecode/BasicBlock.cpp index 8a931e0e62..959dfc1b23 100644 --- a/Userland/Libraries/LibJS/Bytecode/BasicBlock.cpp +++ b/Userland/Libraries/LibJS/Bytecode/BasicBlock.cpp @@ -33,8 +33,18 @@ BasicBlock::~BasicBlock() void BasicBlock::dump(Bytecode::Executable const& executable) const { Bytecode::InstructionStreamIterator it(instruction_stream()); + if (!m_name.is_empty()) - warnln("{}:", m_name); + warn("{}", m_name); + if (m_handler || m_finalizer) { + warn(" ["); + if (m_handler) + warn(" Handler: {}", Label { *m_handler }); + if (m_finalizer) + warn(" Finalizer: {}", Label { *m_finalizer }); + warn(" ]"); + } + warnln(":"); while (!it.at_end()) { warnln("[{:4x}] {}", it.offset(), (*it).to_deprecated_string(executable)); ++it; diff --git a/Userland/Libraries/LibJS/Bytecode/BasicBlock.h b/Userland/Libraries/LibJS/Bytecode/BasicBlock.h index cb4d6d05f3..f3b5b65520 100644 --- a/Userland/Libraries/LibJS/Bytecode/BasicBlock.h +++ b/Userland/Libraries/LibJS/Bytecode/BasicBlock.h @@ -43,10 +43,18 @@ public: DeprecatedString const& name() const { return m_name; } + void set_handler(BasicBlock const& handler) { m_handler = &handler; } + void set_finalizer(BasicBlock const& finalizer) { m_finalizer = &finalizer; } + + BasicBlock const* handler() const { return m_handler; } + BasicBlock const* finalizer() const { return m_finalizer; } + private: explicit BasicBlock(DeprecatedString name); Vector m_buffer; + BasicBlock const* m_handler { nullptr }; + BasicBlock const* m_finalizer { nullptr }; DeprecatedString m_name; bool m_terminated { false }; }; diff --git a/Userland/Libraries/LibJS/Bytecode/Executable.h b/Userland/Libraries/LibJS/Bytecode/Executable.h index 27f48d047c..a3cfbca349 100644 --- a/Userland/Libraries/LibJS/Bytecode/Executable.h +++ b/Userland/Libraries/LibJS/Bytecode/Executable.h @@ -7,10 +7,12 @@ #pragma once #include +#include #include #include #include #include +#include #include #include #include @@ -57,6 +59,7 @@ public: NonnullOwnPtr string_table; NonnullOwnPtr identifier_table; NonnullOwnPtr regex_table; + NonnullRefPtr source_code; size_t number_of_registers { 0 }; bool is_strict_mode { false }; diff --git a/Userland/Libraries/LibJS/Bytecode/Generator.cpp b/Userland/Libraries/LibJS/Bytecode/Generator.cpp index ea67dfdcfc..773bd9ea0d 100644 --- a/Userland/Libraries/LibJS/Bytecode/Generator.cpp +++ b/Userland/Libraries/LibJS/Bytecode/Generator.cpp @@ -4,6 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include #include @@ -95,6 +96,20 @@ Generator::SourceLocationScope::~SourceLocationScope() m_generator.m_current_ast_node = m_previous_node; } +Generator::UnwindContext::UnwindContext(Generator& generator, Optional