From 7d40763c88d98c0384329ee119de52dac748a91e Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Tue, 4 Jun 2024 15:21:22 +0200 Subject: [PATCH] Cache parse trees in `Semantics` --- crates/hir-expand/src/lib.rs | 5 +++-- crates/hir/src/semantics.rs | 20 ++++++++++++++++++-- crates/hir/src/semantics/source_to_def.rs | 1 + 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/crates/hir-expand/src/lib.rs b/crates/hir-expand/src/lib.rs index 131625a96a..a586b543c8 100644 --- a/crates/hir-expand/src/lib.rs +++ b/crates/hir-expand/src/lib.rs @@ -411,7 +411,7 @@ impl MacroFileIdExt for MacroFileId { fn is_attr_macro(&self, db: &dyn ExpandDatabase) -> bool { matches!( db.lookup_intern_macro_call(self.macro_call_id).def.kind, - MacroDefKind::BuiltInAttr(..) | MacroDefKind::ProcMacro(_, ProcMacroKind::Attr, _) + MacroDefKind::BuiltInAttr(..) | MacroDefKind::ProcMacro(_, _, ProcMacroKind::Attr) ) } @@ -721,7 +721,7 @@ impl ExpansionInfo { pub fn is_attr(&self) -> bool { matches!( self.loc.def.kind, - MacroDefKind::BuiltInAttr(..) | MacroDefKind::ProcMacro(_, ProcMacroKind::Attr, _) + MacroDefKind::BuiltInAttr(..) | MacroDefKind::ProcMacro(_, _, ProcMacroKind::Attr) ) } @@ -809,6 +809,7 @@ impl ExpansionInfo { } pub fn new(db: &dyn ExpandDatabase, macro_file: MacroFileId) -> ExpansionInfo { + let _p = tracing::span!(tracing::Level::INFO, "ExpansionInfo::new").entered(); let loc = db.lookup_intern_macro_call(macro_file.macro_call_id); let arg_tt = loc.kind.arg(db); diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs index 8427ca38be..a70dc5254c 100644 --- a/crates/hir/src/semantics.rs +++ b/crates/hir/src/semantics.rs @@ -132,6 +132,9 @@ pub struct SemanticsImpl<'db> { s2d_cache: RefCell, /// Rootnode to HirFileId cache root_to_file_cache: RefCell>, + /// HirFileId to Rootnode cache (this adds a layer over the database LRU cache to prevent + /// possibly frequent invalidation) + parse_cache: RefCell>, /// MacroCall to its expansion's MacroFileId cache macro_call_cache: RefCell, MacroFileId>>, } @@ -292,6 +295,7 @@ impl<'db> SemanticsImpl<'db> { db, s2d_cache: Default::default(), root_to_file_cache: Default::default(), + parse_cache: Default::default(), macro_call_cache: Default::default(), } } @@ -303,6 +307,9 @@ impl<'db> SemanticsImpl<'db> { } pub fn parse_or_expand(&self, file_id: HirFileId) -> SyntaxNode { + if let Some(root) = self.parse_cache.borrow().get(&file_id) { + return root.clone(); + } let node = self.db.parse_or_expand(file_id); self.cache(node.clone(), file_id); node @@ -977,6 +984,13 @@ impl<'db> SemanticsImpl<'db> { let helpers = def_map.derive_helpers_in_scope(InFile::new(file_id, id))?; + if !helpers.is_empty() { + let text_range = attr.syntax().text_range(); + // remove any other token in this macro input, all their mappings are the + // same as this + tokens.retain(|t| !text_range.contains_range(t.text_range())); + } + let mut res = None; for (.., derive) in helpers.iter().filter(|(helper, ..)| *helper == attr_name) @@ -1407,6 +1421,7 @@ impl<'db> SemanticsImpl<'db> { where Def::Ast: AstNode, { + // FIXME: source call should go through the parse cache let res = def.source(self.db)?; self.cache(find_root(res.value.syntax()), res.file_id); Some(res) @@ -1464,8 +1479,9 @@ impl<'db> SemanticsImpl<'db> { fn cache(&self, root_node: SyntaxNode, file_id: HirFileId) { assert!(root_node.parent().is_none()); let mut cache = self.root_to_file_cache.borrow_mut(); - let prev = cache.insert(root_node, file_id); - assert!(prev.is_none() || prev == Some(file_id)) + let prev = cache.insert(root_node.clone(), file_id); + assert!(prev.is_none() || prev == Some(file_id)); + self.parse_cache.borrow_mut().insert(file_id, root_node); } pub fn assert_contains_node(&self, node: &SyntaxNode) { diff --git a/crates/hir/src/semantics/source_to_def.rs b/crates/hir/src/semantics/source_to_def.rs index de24b7d201..85e7c31ddf 100644 --- a/crates/hir/src/semantics/source_to_def.rs +++ b/crates/hir/src/semantics/source_to_def.rs @@ -405,6 +405,7 @@ impl SourceToDefCtx<'_, '_> { } pub(super) fn find_container(&mut self, src: InFile<&SyntaxNode>) -> Option { + let _p = tracing::span!(tracing::Level::INFO, "find_container").entered(); let def = self.ancestors_with_macros(src, |this, container| this.container_to_def(container)); if let Some(def) = def {