Browse Source

LibJS: Fix codegen for nodes after try statements without 'finally'

Previously we were just dropping them on the ground :P
Ali Mohammad Pur 3 years ago
parent
commit
b96118b5d1

+ 9 - 2
Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp

@@ -1189,8 +1189,15 @@ void TryStatement::generate_bytecode(Bytecode::Generator& generator) const
 
     generator.switch_to_basic_block(target_block);
     m_block->generate_bytecode(generator);
-    if (m_finalizer && !generator.is_current_block_terminated())
-        generator.emit<Bytecode::Op::Jump>(finalizer_target);
+    if (!generator.is_current_block_terminated()) {
+        if (m_finalizer) {
+            generator.emit<Bytecode::Op::Jump>(finalizer_target);
+        } else {
+            auto& block = generator.make_block();
+            generator.emit<Bytecode::Op::FinishUnwind>(Bytecode::Label { block });
+            next_block = &block;
+        }
+    }
 
     generator.switch_to_basic_block(next_block ? *next_block : saved_block);
 }

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

@@ -24,6 +24,7 @@
     O(Div)                           \
     O(EnterUnwindContext)            \
     O(Exp)                           \
+    O(FinishUnwind)                  \
     O(GetById)                       \
     O(GetByValue)                    \
     O(GetIterator)                   \

+ 17 - 0
Userland/Libraries/LibJS/Bytecode/Op.cpp

@@ -446,6 +446,18 @@ void EnterUnwindContext::replace_references_impl(BasicBlock const& from, BasicBl
         m_finalizer_target = Label { to };
 }
 
+void FinishUnwind::execute_impl(Bytecode::Interpreter& interpreter) const
+{
+    interpreter.leave_unwind_context();
+    interpreter.jump(m_next_target);
+}
+
+void FinishUnwind::replace_references_impl(BasicBlock const& from, BasicBlock const& to)
+{
+    if (&m_next_target.block() == &from)
+        m_next_target = Label { to };
+}
+
 void LeaveUnwindContext::execute_impl(Bytecode::Interpreter& interpreter) const
 {
     interpreter.leave_unwind_context();
@@ -751,6 +763,11 @@ String EnterUnwindContext::to_string_impl(Bytecode::Executable const&) const
     return String::formatted("EnterUnwindContext handler:{} finalizer:{} entry:{}", handler_string, finalizer_string, m_entry_point);
 }
 
+String FinishUnwind::to_string_impl(const Bytecode::Executable&) const
+{
+    return String::formatted("FinishUnwind next:{}", m_next_target);
+}
+
 String LeaveUnwindContext::to_string_impl(Bytecode::Executable const&) const
 {
     return "LeaveUnwindContext";

+ 16 - 0
Userland/Libraries/LibJS/Bytecode/Op.h

@@ -610,6 +610,22 @@ public:
     void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
 };
 
+class FinishUnwind final : public Instruction {
+public:
+    FinishUnwind(Label next)
+        : Instruction(Type::FinishUnwind)
+        , m_next_target(move(next))
+    {
+    }
+
+    void execute_impl(Bytecode::Interpreter&) const;
+    String to_string_impl(Bytecode::Executable const&) const;
+    void replace_references_impl(BasicBlock const&, BasicBlock const&);
+
+private:
+    Label m_next_target;
+};
+
 class ContinuePendingUnwind final : public Instruction {
 public:
     constexpr static bool IsTerminator = true;