Преглед изворни кода

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.
Simon Wanner пре 1 година
родитељ
комит
ddce5e03c2
1 измењених фајлова са 11 додато и 4 уклоњено
  1. 11 4
      Userland/Libraries/LibJS/JIT/Compiler.cpp

+ 11 - 4
Userland/Libraries/LibJS/JIT/Compiler.cpp

@@ -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);