LibJS: Collapse handler/finalizer into single exception handler target
After replacing the runtime unwind context stack with explicit completion records for try/finally dispatch, the distinction between "handler" (catch) and "finalizer" (finally) in the exception handler table is no longer meaningful at runtime. handle_exception() checked handler first, then finalizer, but they did the exact same thing (set the PC). When both were present, the finalizer was dead code. Collapse both fields into a single handler_offset (now non-optional, since an entry always has a target), remove the finalizer concept from BasicBlock, UnwindContext, and ExceptionHandlers, and simplify handle_exception() to a direct assignment.
This commit is contained in:
parent
4fa4ecf31b
commit
720fd567b1
7 changed files with 14 additions and 36 deletions
|
|
@ -2948,7 +2948,7 @@ Bytecode::CodeGenerationErrorOr<Optional<ScopedOperand>> TryStatement::generate_
|
|||
if (!m_finalizer) {
|
||||
auto const* parent_unwind_context = generator.current_unwind_context();
|
||||
if (parent_unwind_context)
|
||||
unwind_context.emplace(generator, parent_unwind_context->finalizer());
|
||||
unwind_context.emplace(generator, parent_unwind_context->handler());
|
||||
else
|
||||
unwind_context.emplace(generator, OptionalNone());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,10 +42,8 @@ public:
|
|||
String 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; }
|
||||
|
||||
auto const& source_map() const { return m_source_map; }
|
||||
void add_source_map_entry(u32 bytecode_offset, SourceRecord const& source_record) { m_source_map.append({ bytecode_offset, source_record }); }
|
||||
|
|
@ -62,7 +60,6 @@ private:
|
|||
u32 m_index { 0 };
|
||||
Vector<u8> m_buffer;
|
||||
BasicBlock const* m_handler { nullptr };
|
||||
BasicBlock const* m_finalizer { nullptr };
|
||||
String m_name;
|
||||
bool m_terminated { false };
|
||||
bool m_has_resolved_this { false };
|
||||
|
|
|
|||
|
|
@ -81,11 +81,10 @@ void Executable::dump() const
|
|||
warnln("");
|
||||
warnln("Exception handlers:");
|
||||
for (auto& handlers : exception_handlers) {
|
||||
warnln(" from {:4x} to {:4x} handler {:4x} finalizer {:4x}",
|
||||
warnln(" from {:4x} to {:4x} handler {:4x}",
|
||||
handlers.start_offset,
|
||||
handlers.end_offset,
|
||||
handlers.handler_offset.value_or(0),
|
||||
handlers.finalizer_offset.value_or(0));
|
||||
handlers.handler_offset);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -140,8 +140,7 @@ public:
|
|||
struct ExceptionHandlers {
|
||||
size_t start_offset;
|
||||
size_t end_offset;
|
||||
Optional<size_t> handler_offset;
|
||||
Optional<size_t> finalizer_offset;
|
||||
size_t handler_offset;
|
||||
};
|
||||
|
||||
Vector<ExceptionHandlers> exception_handlers;
|
||||
|
|
|
|||
|
|
@ -301,7 +301,6 @@ CodeGenerationErrorOr<GC::Ref<Executable>> Generator::compile(VM& vm, ASTNode co
|
|||
size_t start_offset;
|
||||
size_t end_offset;
|
||||
BasicBlock const* handler;
|
||||
BasicBlock const* finalizer;
|
||||
};
|
||||
Vector<UnlinkedExceptionHandlers> unlinked_exception_handlers;
|
||||
|
||||
|
|
@ -361,12 +360,11 @@ CodeGenerationErrorOr<GC::Ref<Executable>> Generator::compile(VM& vm, ASTNode co
|
|||
|
||||
for (auto& block : generator.m_root_basic_blocks) {
|
||||
basic_block_start_offsets.append(bytecode.size());
|
||||
if (block->handler() || block->finalizer()) {
|
||||
if (block->handler()) {
|
||||
unlinked_exception_handlers.append({
|
||||
.start_offset = bytecode.size(),
|
||||
.end_offset = 0,
|
||||
.handler = block->handler(),
|
||||
.finalizer = block->finalizer(),
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -453,7 +451,7 @@ CodeGenerationErrorOr<GC::Ref<Executable>> Generator::compile(VM& vm, ASTNode co
|
|||
Op::End end(*undefined_constant);
|
||||
bytecode.append(reinterpret_cast<u8 const*>(&end), end.length());
|
||||
}
|
||||
if (block->handler() || block->finalizer()) {
|
||||
if (block->handler()) {
|
||||
unlinked_exception_handlers.last().end_offset = bytecode.size();
|
||||
}
|
||||
}
|
||||
|
|
@ -483,18 +481,17 @@ CodeGenerationErrorOr<GC::Ref<Executable>> Generator::compile(VM& vm, ASTNode co
|
|||
for (auto& unlinked_handler : unlinked_exception_handlers) {
|
||||
auto start_offset = unlinked_handler.start_offset;
|
||||
auto end_offset = unlinked_handler.end_offset;
|
||||
auto handler_offset = unlinked_handler.handler ? block_offsets.get(unlinked_handler.handler).value() : Optional<size_t> {};
|
||||
auto finalizer_offset = unlinked_handler.finalizer ? block_offsets.get(unlinked_handler.finalizer).value() : Optional<size_t> {};
|
||||
auto handler_offset = block_offsets.get(unlinked_handler.handler).value();
|
||||
|
||||
auto maybe_exception_handler_to_merge_with = linked_exception_handlers.find_if([&](Executable::ExceptionHandlers const& exception_handler) {
|
||||
return exception_handler.end_offset == start_offset && exception_handler.handler_offset == handler_offset && exception_handler.finalizer_offset == finalizer_offset;
|
||||
return exception_handler.end_offset == start_offset && exception_handler.handler_offset == handler_offset;
|
||||
});
|
||||
|
||||
if (!maybe_exception_handler_to_merge_with.is_end()) {
|
||||
auto& exception_handler_to_merge_with = *maybe_exception_handler_to_merge_with;
|
||||
exception_handler_to_merge_with.end_offset = end_offset;
|
||||
} else {
|
||||
linked_exception_handlers.append({ start_offset, end_offset, handler_offset, finalizer_offset });
|
||||
linked_exception_handlers.append({ start_offset, end_offset, handler_offset });
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -586,9 +583,9 @@ Generator::SourceLocationScope::~SourceLocationScope()
|
|||
m_generator.m_current_ast_node = m_previous_node;
|
||||
}
|
||||
|
||||
Generator::UnwindContext::UnwindContext(Generator& generator, Optional<Label> finalizer)
|
||||
Generator::UnwindContext::UnwindContext(Generator& generator, Optional<Label> handler)
|
||||
: m_generator(generator)
|
||||
, m_finalizer(finalizer)
|
||||
, m_handler(handler)
|
||||
, m_previous_context(m_generator.m_current_unwind_context)
|
||||
{
|
||||
m_generator.m_current_unwind_context = this;
|
||||
|
|
|
|||
|
|
@ -69,18 +69,16 @@ public:
|
|||
|
||||
class UnwindContext {
|
||||
public:
|
||||
UnwindContext(Generator&, Optional<Label> finalizer);
|
||||
UnwindContext(Generator&, Optional<Label> handler);
|
||||
|
||||
UnwindContext const* previous() const { return m_previous_context; }
|
||||
void set_handler(Label handler) { m_handler = handler; }
|
||||
Optional<Label> handler() const { return m_handler; }
|
||||
Optional<Label> finalizer() const { return m_finalizer; }
|
||||
|
||||
~UnwindContext();
|
||||
|
||||
private:
|
||||
Generator& m_generator;
|
||||
Optional<Label> m_finalizer;
|
||||
Optional<Label> m_handler {};
|
||||
UnwindContext const* m_previous_context { nullptr };
|
||||
};
|
||||
|
|
@ -239,8 +237,6 @@ public:
|
|||
if (auto const* context = m_current_unwind_context) {
|
||||
if (context->handler().has_value())
|
||||
block->set_handler(*m_root_basic_blocks[context->handler().value().basic_block_index()]);
|
||||
if (m_current_unwind_context->finalizer().has_value())
|
||||
block->set_finalizer(*m_root_basic_blocks[context->finalizer().value().basic_block_index()]);
|
||||
}
|
||||
m_root_basic_blocks.append(move(block));
|
||||
return *m_root_basic_blocks.last();
|
||||
|
|
|
|||
|
|
@ -235,18 +235,8 @@ Interpreter::HandleExceptionResponse Interpreter::handle_exception(u32& program_
|
|||
if (!handlers.has_value()) {
|
||||
return HandleExceptionResponse::ExitFromExecutable;
|
||||
}
|
||||
auto& handler = handlers->handler_offset;
|
||||
auto& finalizer = handlers->finalizer_offset;
|
||||
|
||||
if (handler.has_value()) {
|
||||
program_counter = handler.value();
|
||||
return HandleExceptionResponse::ContinueInThisExecutable;
|
||||
}
|
||||
if (finalizer.has_value()) {
|
||||
program_counter = finalizer.value();
|
||||
return HandleExceptionResponse::ContinueInThisExecutable;
|
||||
}
|
||||
VERIFY_NOT_REACHED();
|
||||
program_counter = handlers->handler_offset;
|
||||
return HandleExceptionResponse::ContinueInThisExecutable;
|
||||
}
|
||||
|
||||
void Interpreter::run_bytecode(size_t entry_point)
|
||||
|
|
|
|||
Loading…
Reference in a new issue