From b4b9c4b3836238cb51e9cd4fdfb44047d3e42cdb Mon Sep 17 00:00:00 2001 From: Hendiadyoin1 Date: Thu, 11 Apr 2024 11:07:35 +0200 Subject: [PATCH] LibJS: Restore scheduled jumps in catch blocks without finalizers --- Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp | 4 +++- Userland/Libraries/LibJS/Bytecode/Instruction.h | 1 + .../Libraries/LibJS/Bytecode/Interpreter.cpp | 16 ++++++++++++++++ Userland/Libraries/LibJS/Bytecode/Interpreter.h | 1 + Userland/Libraries/LibJS/Bytecode/Op.h | 11 +++++++++++ 5 files changed, 32 insertions(+), 1 deletion(-) diff --git a/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp b/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp index cd997b3be15..6118ec5c032 100644 --- a/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp +++ b/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp @@ -2461,8 +2461,10 @@ Bytecode::CodeGenerationErrorOr> TryStatement::gener auto caught_value = Bytecode::Operand { generator.allocate_register() }; generator.emit(caught_value); - if (!m_finalizer) + if (!m_finalizer) { generator.emit(); + generator.emit(); + } // OPTIMIZATION: We avoid creating a lexical environment if the catch clause has no parameter. bool did_create_variable_scope_for_catch_clause = false; diff --git a/Userland/Libraries/LibJS/Bytecode/Instruction.h b/Userland/Libraries/LibJS/Bytecode/Instruction.h index 31d9f7d7eb0..947f0affb3d 100644 --- a/Userland/Libraries/LibJS/Bytecode/Instruction.h +++ b/Userland/Libraries/LibJS/Bytecode/Instruction.h @@ -98,6 +98,7 @@ O(PutPrivateById) \ O(ResolveThisBinding) \ O(ResolveSuperBase) \ + O(RestoreScheduledJump) \ O(Return) \ O(RightShift) \ O(ScheduleJump) \ diff --git a/Userland/Libraries/LibJS/Bytecode/Interpreter.cpp b/Userland/Libraries/LibJS/Bytecode/Interpreter.cpp index a7465a790c1..44b9b749753 100644 --- a/Userland/Libraries/LibJS/Bytecode/Interpreter.cpp +++ b/Userland/Libraries/LibJS/Bytecode/Interpreter.cpp @@ -537,6 +537,11 @@ void Interpreter::catch_exception(Operand dst) vm().running_execution_context().lexical_environment = context.lexical_environment; } +void Interpreter::restore_scheduled_jump() +{ + m_scheduled_jump = call_frame().previously_scheduled_jumps.take_last(); +} + void Interpreter::enter_object_environment(Object& object) { auto& running_execution_context = vm().running_execution_context(); @@ -1020,6 +1025,12 @@ ThrowCompletionOr Catch::execute_impl(Bytecode::Interpreter& interpreter) return {}; } +ThrowCompletionOr RestoreScheduledJump::execute_impl(Bytecode::Interpreter& interpreter) const +{ + interpreter.restore_scheduled_jump(); + return {}; +} + ThrowCompletionOr CreateVariable::execute_impl(Bytecode::Interpreter& interpreter) const { auto const& name = interpreter.current_executable().get_identifier(m_identifier); @@ -2231,6 +2242,11 @@ ByteString Catch::to_byte_string_impl(Bytecode::Executable const& executable) co format_operand("dst"sv, m_dst, executable)); } +ByteString RestoreScheduledJump::to_byte_string_impl(Bytecode::Executable const&) const +{ + return ByteString::formatted("RestoreScheduledJump"); +} + ByteString GetObjectFromIteratorRecord::to_byte_string_impl(Bytecode::Executable const& executable) const { return ByteString::formatted("GetObjectFromIteratorRecord {}, {}", diff --git a/Userland/Libraries/LibJS/Bytecode/Interpreter.h b/Userland/Libraries/LibJS/Bytecode/Interpreter.h index f92b4d5d886..cea2f37725c 100644 --- a/Userland/Libraries/LibJS/Bytecode/Interpreter.h +++ b/Userland/Libraries/LibJS/Bytecode/Interpreter.h @@ -68,6 +68,7 @@ public: void enter_unwind_context(); void leave_unwind_context(); void catch_exception(Operand dst); + void restore_scheduled_jump(); void enter_object_environment(Object&); diff --git a/Userland/Libraries/LibJS/Bytecode/Op.h b/Userland/Libraries/LibJS/Bytecode/Op.h index 7c91b2f095c..81ab0769d17 100644 --- a/Userland/Libraries/LibJS/Bytecode/Op.h +++ b/Userland/Libraries/LibJS/Bytecode/Op.h @@ -452,6 +452,17 @@ private: Operand m_dst; }; +class RestoreScheduledJump final : public Instruction { +public: + explicit RestoreScheduledJump() + : Instruction(Type::RestoreScheduledJump, sizeof(*this)) + { + } + + ThrowCompletionOr execute_impl(Bytecode::Interpreter&) const; + ByteString to_byte_string_impl(Bytecode::Executable const&) const; +}; + class CreateVariable final : public Instruction { public: explicit CreateVariable(IdentifierTableIndex identifier, EnvironmentMode mode, bool is_immutable, bool is_global = false, bool is_strict = false)