Selaa lähdekoodia

LibJS: Don't track executing AST nodes in a Vector

Instead just link together the InterpreterNodeScopes in a linked list.
This was surprisingly hot on CanvasCycle.
Andreas Kling 4 vuotta sitten
vanhempi
commit
e0abfcb27d

+ 6 - 6
Userland/Libraries/LibJS/AST.cpp

@@ -59,19 +59,20 @@ class InterpreterNodeScope {
 public:
 public:
     InterpreterNodeScope(Interpreter& interpreter, const ASTNode& node)
     InterpreterNodeScope(Interpreter& interpreter, const ASTNode& node)
         : m_interpreter(interpreter)
         : m_interpreter(interpreter)
-        , m_node(node)
+        , m_chain_node { nullptr, node }
     {
     {
-        m_interpreter.enter_node(m_node);
+        m_interpreter.vm().call_frame().current_node = &node;
+        m_interpreter.push_ast_node(m_chain_node);
     }
     }
 
 
     ~InterpreterNodeScope()
     ~InterpreterNodeScope()
     {
     {
-        m_interpreter.exit_node(m_node);
+        m_interpreter.pop_ast_node();
     }
     }
 
 
 private:
 private:
     Interpreter& m_interpreter;
     Interpreter& m_interpreter;
-    const ASTNode& m_node;
+    ExecutingASTNodeChain m_chain_node;
 };
 };
 
 
 String ASTNode::class_name() const
 String ASTNode::class_name() const
@@ -2169,8 +2170,7 @@ void SequenceExpression::dump(int indent) const
 
 
 Value SequenceExpression::execute(Interpreter& interpreter, GlobalObject& global_object) const
 Value SequenceExpression::execute(Interpreter& interpreter, GlobalObject& global_object) const
 {
 {
-    interpreter.enter_node(*this);
-    ScopeGuard exit_node { [&] { interpreter.exit_node(*this); } };
+    InterpreterNodeScope node_scope { interpreter, *this };
 
 
     Value last_value;
     Value last_value;
     for (auto& expression : m_expressions) {
     for (auto& expression : m_expressions) {

+ 0 - 11
Userland/Libraries/LibJS/Interpreter.cpp

@@ -143,17 +143,6 @@ void Interpreter::exit_scope(const ScopeNode& scope_node)
         vm().unwind(ScopeType::None);
         vm().unwind(ScopeType::None);
 }
 }
 
 
-void Interpreter::enter_node(const ASTNode& node)
-{
-    vm().call_frame().current_node = &node;
-    push_ast_node(node);
-}
-
-void Interpreter::exit_node(const ASTNode&)
-{
-    pop_ast_node();
-}
-
 void Interpreter::push_scope(ScopeFrame frame)
 void Interpreter::push_scope(ScopeFrame frame)
 {
 {
     m_scope_stack.append(move(frame));
     m_scope_stack.append(move(frame));

+ 19 - 7
Userland/Libraries/LibJS/Interpreter.h

@@ -44,6 +44,11 @@
 
 
 namespace JS {
 namespace JS {
 
 
+struct ExecutingASTNodeChain {
+    ExecutingASTNodeChain* previous { nullptr };
+    const ASTNode& node;
+};
+
 class Interpreter : public Weakable<Interpreter> {
 class Interpreter : public Weakable<Interpreter> {
 public:
 public:
     template<typename GlobalObjectType, typename... Args>
     template<typename GlobalObjectType, typename... Args>
@@ -77,14 +82,21 @@ public:
     void enter_scope(const ScopeNode&, ScopeType, GlobalObject&);
     void enter_scope(const ScopeNode&, ScopeType, GlobalObject&);
     void exit_scope(const ScopeNode&);
     void exit_scope(const ScopeNode&);
 
 
-    void enter_node(const ASTNode&);
-    void exit_node(const ASTNode&);
+    void push_ast_node(ExecutingASTNodeChain& chain_node)
+    {
+        chain_node.previous = m_ast_node_chain;
+        m_ast_node_chain = &chain_node;
+    }
 
 
-    void push_ast_node(const ASTNode& node) { m_ast_nodes.append(&node); }
-    void pop_ast_node() { m_ast_nodes.take_last(); }
+    void pop_ast_node()
+    {
+        VERIFY(m_ast_node_chain);
+        m_ast_node_chain = m_ast_node_chain->previous;
+    }
 
 
-    const ASTNode* current_node() const { return !m_ast_nodes.is_empty() ? m_ast_nodes.last() : nullptr; }
-    const Vector<const ASTNode*>& node_stack() const { return m_ast_nodes; }
+    const ASTNode* current_node() const { return m_ast_node_chain ? &m_ast_node_chain->node : nullptr; }
+    ExecutingASTNodeChain* executing_ast_node_chain() { return m_ast_node_chain; }
+    const ExecutingASTNodeChain* executing_ast_node_chain() const { return m_ast_node_chain; }
 
 
     Value execute_statement(GlobalObject&, const Statement&, ScopeType = ScopeType::Block);
     Value execute_statement(GlobalObject&, const Statement&, ScopeType = ScopeType::Block);
 
 
@@ -94,7 +106,7 @@ private:
     void push_scope(ScopeFrame frame);
     void push_scope(ScopeFrame frame);
 
 
     Vector<ScopeFrame> m_scope_stack;
     Vector<ScopeFrame> m_scope_stack;
-    Vector<const ASTNode*> m_ast_nodes;
+    ExecutingASTNodeChain* m_ast_node_chain { nullptr };
 
 
     NonnullRefPtr<VM> m_vm;
     NonnullRefPtr<VM> m_vm;
 
 

+ 2 - 5
Userland/Libraries/LibJS/Runtime/Exception.cpp

@@ -45,11 +45,8 @@ Exception::Exception(Value value)
     }
     }
 
 
     if (auto* interpreter = vm.interpreter_if_exists()) {
     if (auto* interpreter = vm.interpreter_if_exists()) {
-        auto& node_stack = interpreter->node_stack();
-        for (ssize_t i = node_stack.size() - 1; i >= 0; --i) {
-            auto* node = node_stack[i];
-            VERIFY(node);
-            m_source_ranges.append(node->source_range());
+        for (auto* node_chain = interpreter->executing_ast_node_chain(); node_chain; node_chain = node_chain->previous) {
+            m_source_ranges.append(node_chain->node.source_range());
         }
         }
     }
     }
 }
 }