LibCpp: Don't store entire ASTNode vector in each parser state

We previously stored the entire ASTNode vector in each parser state,
and this vector was copied whenever a state was loaded or saved.

We don't actually need to store the whole nodes list in each state
because a new state can only add new nodes to this list, and won't
mutate existing nodes.

It would suffice to only hold a vector of the nodes that were created
while parsing in the current state to keep a reference to them.

This reduces the time it takes on my machine for the c++ language
server to handle a file that #includes <LibGUI/Widget.h> from ~4sec to
~0.7sec.
This commit is contained in:
Itamar 2021-07-13 22:07:05 +03:00 committed by Andreas Kling
parent eb6a15d52b
commit 42eb06f045
Notes: sideshowbarker 2024-07-18 09:06:45 +09:00
2 changed files with 17 additions and 16 deletions

View file

@ -851,6 +851,7 @@ Optional<Token> Parser::peek(Token::Type type) const
void Parser::save_state()
{
m_saved_states.append(m_state);
m_state.state_nodes.clear();
}
void Parser::load_state()
@ -897,7 +898,7 @@ void Parser::error(StringView message)
if (!m_saved_states.is_empty())
return;
if (message.is_null() || message.is_empty())
message = "<empty>";
String formatted_message;
@ -941,23 +942,19 @@ Position Parser::position() const
return peek().start();
}
RefPtr<ASTNode> Parser::eof_node() const
{
VERIFY(m_tokens.size());
return node_at(m_tokens.last().end());
}
RefPtr<ASTNode> Parser::node_at(Position pos) const
{
VERIFY(m_saved_states.is_empty());
auto index = index_of_node_at(pos);
if (!index.has_value())
return nullptr;
return m_state.nodes[index.value()];
return m_nodes[index.value()];
}
Optional<size_t> Parser::index_of_node_at(Position pos) const
{
VERIFY(!m_tokens.is_empty());
VERIFY(m_saved_states.is_empty());
Optional<size_t> match_node_index;
auto node_span = [](const ASTNode& node) {
@ -966,12 +963,12 @@ Optional<size_t> Parser::index_of_node_at(Position pos) const
return Position { node.end().line - node.start().line, node.start().line != node.end().line ? 0 : node.end().column - node.start().column };
};
for (size_t node_index = 0; node_index < m_state.nodes.size(); ++node_index) {
auto& node = m_state.nodes[node_index];
for (size_t node_index = 0; node_index < m_nodes.size(); ++node_index) {
auto& node = m_nodes[node_index];
if (node.start() > pos || node.end() < pos)
continue;
if (!match_node_index.has_value() || (node_span(node) <= node_span(m_state.nodes[match_node_index.value()])))
if (!match_node_index.has_value() || (node_span(node) <= node_span(m_nodes[match_node_index.value()])))
match_node_index = node_index;
}
return match_node_index;

View file

@ -24,7 +24,6 @@ public:
NonnullRefPtr<TranslationUnit> parse();
bool eof() const;
RefPtr<ASTNode> eof_node() const;
RefPtr<ASTNode> node_at(Position) const;
Optional<size_t> index_of_node_at(Position) const;
Optional<Token> token_at(Position) const;
@ -147,7 +146,7 @@ private:
struct State {
size_t token_index { 0 };
NonnullRefPtrVector<ASTNode> nodes;
NonnullRefPtrVector<ASTNode> state_nodes;
};
void error(StringView message = {});
@ -157,9 +156,13 @@ private:
create_ast_node(ASTNode& parent, const Position& start, Optional<Position> end, Args&&... args)
{
auto node = adopt_ref(*new T(&parent, start, end, m_filename, forward<Args>(args)...));
if (!parent.is_dummy_node()) {
m_state.nodes.append(node);
if (m_saved_states.is_empty()) {
m_nodes.append(node);
} else {
m_state.state_nodes.append(node);
}
return node;
}
@ -167,7 +170,7 @@ private:
create_root_ast_node(const Position& start, Position end)
{
auto node = adopt_ref(*new TranslationUnit(nullptr, start, end, m_filename));
m_state.nodes.append(node);
m_nodes.append(node);
m_root_node = node;
return node;
}
@ -200,6 +203,7 @@ private:
Vector<State> m_saved_states;
RefPtr<TranslationUnit> m_root_node;
Vector<String> m_errors;
NonnullRefPtrVector<ASTNode> m_nodes;
Vector<TokenAndPreprocessorDefinition> m_replaced_preprocessor_tokens;
};