diff --git a/Userland/Libraries/LibJS/JIT/Compiler.cpp b/Userland/Libraries/LibJS/JIT/Compiler.cpp index 6ad6a18f6a..bb5164b33a 100644 --- a/Userland/Libraries/LibJS/JIT/Compiler.cpp +++ b/Userland/Libraries/LibJS/JIT/Compiler.cpp @@ -214,6 +214,47 @@ void Compiler::check_exception() // handle_exception: handle_exception.link(m_assembler); + // if (unwind_context.handler) { + // accumulator = exception; + // exception = Value(); + // goto handler; + // } + auto no_handler = m_assembler.make_label(); + m_assembler.mov( + Assembler::Operand::Register(GPR0), + Assembler::Operand::Mem64BaseAndOffset(UNWIND_CONTEXT_BASE, 8)); + m_assembler.jump_if_equal( + Assembler::Operand::Register(GPR0), + Assembler::Operand::Imm32(0), + no_handler); + load_vm_register(GPR1, Bytecode::Register::exception()); + store_vm_register(Bytecode::Register::accumulator(), GPR1); + m_assembler.mov( + Assembler::Operand::Register(GPR1), + Assembler::Operand::Imm64(Value().encoded())); + store_vm_register(Bytecode::Register::exception(), GPR1); + m_assembler.jump(Assembler::Operand::Register(GPR0)); + + // no_handler: + no_handler.link(m_assembler); + + // if (unwind_context.finalizer) goto finalizer; + auto no_finalizer = m_assembler.make_label(); + m_assembler.mov( + Assembler::Operand::Register(GPR0), + Assembler::Operand::Mem64BaseAndOffset(UNWIND_CONTEXT_BASE, 16)); + m_assembler.jump_if_equal( + Assembler::Operand::Register(GPR0), + Assembler::Operand::Imm32(0), + no_finalizer); + + m_assembler.jump(Assembler::Operand::Register(GPR0)); + + // no_finalizer: + // NOTE: No catch and no finally!? Crash. + no_finalizer.link(m_assembler); + m_assembler.verify_not_reached(); + // no_exception: no_exception.link(m_assembler); } @@ -230,7 +271,7 @@ void Compiler::push_unwind_context(bool valid, Optional const& // push finalizer (patched later) m_assembler.mov( Assembler::Operand::Register(GPR0), - Assembler::Operand::Imm64(0xdeadbeef)); + Assembler::Operand::Imm64(0)); if (finalizer.has_value()) const_cast(finalizer.value().block()).absolute_references_to_here.append(m_assembler.m_output.size() - 8); m_assembler.push(Assembler::Operand::Register(GPR0)); @@ -238,7 +279,7 @@ void Compiler::push_unwind_context(bool valid, Optional const& // push handler (patched later) m_assembler.mov( Assembler::Operand::Register(GPR0), - Assembler::Operand::Imm64(0xdeadbeef)); + Assembler::Operand::Imm64(0)); if (handler.has_value()) const_cast(handler.value().block()).absolute_references_to_here.append(m_assembler.m_output.size() - 8); m_assembler.push(Assembler::Operand::Register(GPR0)); @@ -261,6 +302,18 @@ void Compiler::pop_unwind_context() m_assembler.add(Assembler::Operand::Register(UNWIND_CONTEXT_BASE), Assembler::Operand::Imm8(32)); } +void Compiler::compile_enter_unwind_context(Bytecode::Op::EnterUnwindContext const& op) +{ + push_unwind_context(true, op.handler_target(), op.finalizer_target()); + + m_assembler.jump(const_cast(op.entry_point().block())); +} + +void Compiler::compile_leave_unwind_context(Bytecode::Op::LeaveUnwindContext const&) +{ + pop_unwind_context(); +} + OwnPtr Compiler::compile(Bytecode::Executable const& bytecode_executable) { if (getenv("LIBJS_NO_JIT")) @@ -313,6 +366,12 @@ OwnPtr Compiler::compile(Bytecode::Executable const& bytecode_ case Bytecode::Instruction::Type::Increment: compiler.compile_increment(static_cast(op)); break; + case Bytecode::Instruction::Type::EnterUnwindContext: + compiler.compile_enter_unwind_context(static_cast(op)); + break; + case Bytecode::Instruction::Type::LeaveUnwindContext: + compiler.compile_leave_unwind_context(static_cast(op)); + break; default: dbgln("JIT compilation failed: {}", bytecode_executable.name); dbgln("Unsupported bytecode op: {}", op.to_deprecated_string(bytecode_executable)); diff --git a/Userland/Libraries/LibJS/JIT/Compiler.h b/Userland/Libraries/LibJS/JIT/Compiler.h index 805047f76e..368ca71480 100644 --- a/Userland/Libraries/LibJS/JIT/Compiler.h +++ b/Userland/Libraries/LibJS/JIT/Compiler.h @@ -38,6 +38,8 @@ private: void compile_jump_conditional(Bytecode::Op::JumpConditional const&); void compile_less_than(Bytecode::Op::LessThan const&); void compile_increment(Bytecode::Op::Increment const&); + void compile_enter_unwind_context(Bytecode::Op::EnterUnwindContext const&); + void compile_leave_unwind_context(Bytecode::Op::LeaveUnwindContext const&); void store_vm_register(Bytecode::Register, Assembler::Reg); void load_vm_register(Assembler::Reg, Bytecode::Register);