浏览代码

LibJS: Restore scheduled jumps in catch blocks without finalizers

Hendiadyoin1 1 年之前
父节点
当前提交
b4b9c4b383

+ 3 - 1
Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp

@@ -2461,8 +2461,10 @@ Bytecode::CodeGenerationErrorOr<Optional<Bytecode::Operand>> TryStatement::gener
         auto caught_value = Bytecode::Operand { generator.allocate_register() };
         generator.emit<Bytecode::Op::Catch>(caught_value);
 
-        if (!m_finalizer)
+        if (!m_finalizer) {
             generator.emit<Bytecode::Op::LeaveUnwindContext>();
+            generator.emit<Bytecode::Op::RestoreScheduledJump>();
+        }
 
         // OPTIMIZATION: We avoid creating a lexical environment if the catch clause has no parameter.
         bool did_create_variable_scope_for_catch_clause = false;

+ 1 - 0
Userland/Libraries/LibJS/Bytecode/Instruction.h

@@ -98,6 +98,7 @@
     O(PutPrivateById)                  \
     O(ResolveThisBinding)              \
     O(ResolveSuperBase)                \
+    O(RestoreScheduledJump)            \
     O(Return)                          \
     O(RightShift)                      \
     O(ScheduleJump)                    \

+ 16 - 0
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<void> Catch::execute_impl(Bytecode::Interpreter& interpreter)
     return {};
 }
 
+ThrowCompletionOr<void> RestoreScheduledJump::execute_impl(Bytecode::Interpreter& interpreter) const
+{
+    interpreter.restore_scheduled_jump();
+    return {};
+}
+
 ThrowCompletionOr<void> 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 {}, {}",

+ 1 - 0
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&);
 

+ 11 - 0
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<void> 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)