LibJS/JIT: Clear unwind context handler on usage

This clears the handler pointer of the current unwind context
before jumping to it. This is necessary to not loop infinitely
when an exception is thrown from the handler.
In that case control flow should go to the finalizer instead.

This mirrors how unwind_context.handler_called is used in the
Bytecode::Interpreter.

`try { throw 1 } catch (e) { throw 2 } finally {}` now runs
without looping infinitely in the catch block.
This commit is contained in:
Simon Wanner 2023-10-29 02:24:51 +02:00 committed by Andreas Kling
commit ddce5e03c2
Notes: sideshowbarker 2024-07-17 01:13:25 +09:00

View file

@ -346,10 +346,6 @@ void Compiler::handle_exception()
handle_exception.link(m_assembler); handle_exception.link(m_assembler);
// if (unwind_context.handler) { // if (unwind_context.handler) {
// accumulator = exception;
// exception = Value();
// goto handler;
// }
Assembler::Label no_handler {}; Assembler::Label no_handler {};
m_assembler.mov( m_assembler.mov(
Assembler::Operand::Register(GPR0), Assembler::Operand::Register(GPR0),
@ -358,13 +354,24 @@ void Compiler::handle_exception()
Assembler::Operand::Register(GPR0), Assembler::Operand::Register(GPR0),
Assembler::Operand::Imm(0), Assembler::Operand::Imm(0),
no_handler); no_handler);
// accumulator = exception;
load_vm_register(GPR1, Bytecode::Register::exception()); load_vm_register(GPR1, Bytecode::Register::exception());
store_vm_register(Bytecode::Register::accumulator(), GPR1); store_vm_register(Bytecode::Register::accumulator(), GPR1);
// exception = Value();
m_assembler.mov( m_assembler.mov(
Assembler::Operand::Register(GPR1), Assembler::Operand::Register(GPR1),
Assembler::Operand::Imm(Value().encoded())); Assembler::Operand::Imm(Value().encoded()));
store_vm_register(Bytecode::Register::exception(), GPR1); store_vm_register(Bytecode::Register::exception(), GPR1);
// unwind_context.handler = nullptr;
m_assembler.mov(
Assembler::Operand::Register(GPR1),
Assembler::Operand::Imm(0));
m_assembler.mov(
Assembler::Operand::Mem64BaseAndOffset(UNWIND_CONTEXT_BASE, 8),
Assembler::Operand::Register(GPR1));
// goto handler;
m_assembler.jump(Assembler::Operand::Register(GPR0)); m_assembler.jump(Assembler::Operand::Register(GPR0));
// }
// no_handler: // no_handler:
no_handler.link(m_assembler); no_handler.link(m_assembler);