1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-06-01 08:28:11 +00:00

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
parent 224f92f6e4
commit ddce5e03c2

View file

@ -346,10 +346,6 @@ void Compiler::handle_exception()
handle_exception.link(m_assembler);
// if (unwind_context.handler) {
// accumulator = exception;
// exception = Value();
// goto handler;
// }
Assembler::Label no_handler {};
m_assembler.mov(
Assembler::Operand::Register(GPR0),
@ -358,13 +354,24 @@ void Compiler::handle_exception()
Assembler::Operand::Register(GPR0),
Assembler::Operand::Imm(0),
no_handler);
// accumulator = exception;
load_vm_register(GPR1, Bytecode::Register::exception());
store_vm_register(Bytecode::Register::accumulator(), GPR1);
// exception = Value();
m_assembler.mov(
Assembler::Operand::Register(GPR1),
Assembler::Operand::Imm(Value().encoded()));
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));
// }
// no_handler:
no_handler.link(m_assembler);