瀏覽代碼

LibJS: Make EnterUnwindContext a terminator op

Otherwise a basic block could have multiple outgoing edges without
having much reason to do so.
Ali Mohammad Pur 4 年之前
父節點
當前提交
4c7c7c38e2

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

@@ -991,8 +991,11 @@ void TryStatement::generate_bytecode(Bytecode::Generator& generator) const
         }
         }
     }
     }
 
 
+    auto& target_block = generator.make_block();
     generator.switch_to_basic_block(saved_block);
     generator.switch_to_basic_block(saved_block);
-    generator.emit<Bytecode::Op::EnterUnwindContext>(handler_target, finalizer_target);
+    generator.emit<Bytecode::Op::EnterUnwindContext>(Bytecode::Label { target_block }, handler_target, finalizer_target);
+
+    generator.switch_to_basic_block(target_block);
     m_block->generate_bytecode(generator);
     m_block->generate_bytecode(generator);
     if (m_finalizer && !generator.is_current_block_terminated())
     if (m_finalizer && !generator.is_current_block_terminated())
         generator.emit<Bytecode::Op::Jump>(finalizer_target);
         generator.emit<Bytecode::Op::Jump>(finalizer_target);

+ 2 - 1
Userland/Libraries/LibJS/Bytecode/Op.cpp

@@ -258,6 +258,7 @@ void Throw::execute(Bytecode::Interpreter& interpreter) const
 void EnterUnwindContext::execute(Bytecode::Interpreter& interpreter) const
 void EnterUnwindContext::execute(Bytecode::Interpreter& interpreter) const
 {
 {
     interpreter.enter_unwind_context(m_handler_target, m_finalizer_target);
     interpreter.enter_unwind_context(m_handler_target, m_finalizer_target);
+    interpreter.jump(m_entry_point);
 }
 }
 
 
 void LeaveUnwindContext::execute(Bytecode::Interpreter& interpreter) const
 void LeaveUnwindContext::execute(Bytecode::Interpreter& interpreter) const
@@ -453,7 +454,7 @@ String EnterUnwindContext::to_string(Bytecode::Executable const&) const
 {
 {
     auto handler_string = m_handler_target.has_value() ? String::formatted("{}", *m_handler_target) : "<empty>";
     auto handler_string = m_handler_target.has_value() ? String::formatted("{}", *m_handler_target) : "<empty>";
     auto finalizer_string = m_finalizer_target.has_value() ? String::formatted("{}", *m_finalizer_target) : "<empty>";
     auto finalizer_string = m_finalizer_target.has_value() ? String::formatted("{}", *m_finalizer_target) : "<empty>";
-    return String::formatted("EnterUnwindContext handler:{} finalizer:{}", handler_string, finalizer_string);
+    return String::formatted("EnterUnwindContext handler:{} finalizer:{} entry:{}", handler_string, finalizer_string, m_entry_point);
 }
 }
 
 
 String LeaveUnwindContext::to_string(Bytecode::Executable const&) const
 String LeaveUnwindContext::to_string(Bytecode::Executable const&) const

+ 5 - 1
Userland/Libraries/LibJS/Bytecode/Op.h

@@ -451,8 +451,11 @@ public:
 
 
 class EnterUnwindContext final : public Instruction {
 class EnterUnwindContext final : public Instruction {
 public:
 public:
-    EnterUnwindContext(Optional<Label> handler_target, Optional<Label> finalizer_target)
+    constexpr static bool IsTerminator = true;
+
+    EnterUnwindContext(Label entry_point, Optional<Label> handler_target, Optional<Label> finalizer_target)
         : Instruction(Type::EnterUnwindContext)
         : Instruction(Type::EnterUnwindContext)
+        , m_entry_point(move(entry_point))
         , m_handler_target(move(handler_target))
         , m_handler_target(move(handler_target))
         , m_finalizer_target(move(finalizer_target))
         , m_finalizer_target(move(finalizer_target))
     {
     {
@@ -462,6 +465,7 @@ public:
     String to_string(Bytecode::Executable const&) const;
     String to_string(Bytecode::Executable const&) const;
 
 
 private:
 private:
+    Label m_entry_point;
     Optional<Label> m_handler_target;
     Optional<Label> m_handler_target;
     Optional<Label> m_finalizer_target;
     Optional<Label> m_finalizer_target;
 };
 };