Skip to content

Commit 035bed8

Browse files
authored
Merge pull request rust-lang#20527 from ChayimFriedman2/cache-next-solver
perf: Cache trait solving across queries in the same revision
2 parents ab5113a + a0aa1c1 commit 035bed8

File tree

7 files changed

+140
-66
lines changed

7 files changed

+140
-66
lines changed

src/tools/rust-analyzer/crates/base-db/src/lib.rs

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,12 @@ pub use salsa_macros;
77
mod change;
88
mod input;
99

10-
use std::{cell::RefCell, hash::BuildHasherDefault, panic, sync::Once};
10+
use std::{
11+
cell::RefCell,
12+
hash::BuildHasherDefault,
13+
panic,
14+
sync::{Once, atomic::AtomicUsize},
15+
};
1116

1217
pub use crate::{
1318
change::FileChange,
@@ -328,6 +333,27 @@ pub trait SourceDatabase: salsa::Database {
328333

329334
#[doc(hidden)]
330335
fn crates_map(&self) -> Arc<CratesMap>;
336+
337+
fn nonce_and_revision(&self) -> (Nonce, salsa::Revision);
338+
}
339+
340+
static NEXT_NONCE: AtomicUsize = AtomicUsize::new(0);
341+
342+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
343+
pub struct Nonce(usize);
344+
345+
impl Default for Nonce {
346+
#[inline]
347+
fn default() -> Self {
348+
Nonce::new()
349+
}
350+
}
351+
352+
impl Nonce {
353+
#[inline]
354+
pub fn new() -> Nonce {
355+
Nonce(NEXT_NONCE.fetch_add(1, std::sync::atomic::Ordering::SeqCst))
356+
}
331357
}
332358

333359
/// Crate related data shared by the whole workspace.

src/tools/rust-analyzer/crates/hir-def/src/test_db.rs

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
use std::{fmt, panic, sync::Mutex};
44

55
use base_db::{
6-
Crate, CrateGraphBuilder, CratesMap, FileSourceRootInput, FileText, RootQueryDb,
6+
Crate, CrateGraphBuilder, CratesMap, FileSourceRootInput, FileText, Nonce, RootQueryDb,
77
SourceDatabase, SourceRoot, SourceRootId, SourceRootInput,
88
};
99
use hir_expand::{InFile, files::FilePosition};
@@ -20,12 +20,12 @@ use crate::{
2020
};
2121

2222
#[salsa_macros::db]
23-
#[derive(Clone)]
2423
pub(crate) struct TestDB {
2524
storage: salsa::Storage<Self>,
2625
files: Arc<base_db::Files>,
2726
crates_map: Arc<CratesMap>,
2827
events: Arc<Mutex<Option<Vec<salsa::Event>>>>,
28+
nonce: Nonce,
2929
}
3030

3131
impl Default for TestDB {
@@ -44,6 +44,7 @@ impl Default for TestDB {
4444
events,
4545
files: Default::default(),
4646
crates_map: Default::default(),
47+
nonce: Nonce::new(),
4748
};
4849
this.set_expand_proc_attr_macros_with_durability(true, Durability::HIGH);
4950
// This needs to be here otherwise `CrateGraphBuilder` panics.
@@ -53,6 +54,18 @@ impl Default for TestDB {
5354
}
5455
}
5556

57+
impl Clone for TestDB {
58+
fn clone(&self) -> Self {
59+
Self {
60+
storage: self.storage.clone(),
61+
files: self.files.clone(),
62+
crates_map: self.crates_map.clone(),
63+
events: self.events.clone(),
64+
nonce: Nonce::new(),
65+
}
66+
}
67+
}
68+
5669
#[salsa_macros::db]
5770
impl salsa::Database for TestDB {}
5871

@@ -117,6 +130,10 @@ impl SourceDatabase for TestDB {
117130
fn crates_map(&self) -> Arc<CratesMap> {
118131
self.crates_map.clone()
119132
}
133+
134+
fn nonce_and_revision(&self) -> (Nonce, salsa::Revision) {
135+
(self.nonce, salsa::plumbing::ZalsaDatabase::zalsa(self).current_revision())
136+
}
120137
}
121138

122139
impl TestDB {

src/tools/rust-analyzer/crates/hir-ty/src/infer.rs

Lines changed: 40 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -88,54 +88,52 @@ pub(crate) use closure::{CaptureKind, CapturedItem, CapturedItemWithoutTy};
8888

8989
/// The entry point of type inference.
9090
pub(crate) fn infer_query(db: &dyn HirDatabase, def: DefWithBodyId) -> Arc<InferenceResult> {
91-
crate::next_solver::with_new_cache(|| {
92-
let _p = tracing::info_span!("infer_query").entered();
93-
let resolver = def.resolver(db);
94-
let body = db.body(def);
95-
let mut ctx = InferenceContext::new(db, def, &body, resolver);
96-
97-
match def {
98-
DefWithBodyId::FunctionId(f) => {
99-
ctx.collect_fn(f);
100-
}
101-
DefWithBodyId::ConstId(c) => ctx.collect_const(c, &db.const_signature(c)),
102-
DefWithBodyId::StaticId(s) => ctx.collect_static(&db.static_signature(s)),
103-
DefWithBodyId::VariantId(v) => {
104-
ctx.return_ty = TyBuilder::builtin(
105-
match db.enum_signature(v.lookup(db).parent).variant_body_type() {
106-
hir_def::layout::IntegerType::Pointer(signed) => match signed {
107-
true => BuiltinType::Int(BuiltinInt::Isize),
108-
false => BuiltinType::Uint(BuiltinUint::Usize),
109-
},
110-
hir_def::layout::IntegerType::Fixed(size, signed) => match signed {
111-
true => BuiltinType::Int(match size {
112-
Integer::I8 => BuiltinInt::I8,
113-
Integer::I16 => BuiltinInt::I16,
114-
Integer::I32 => BuiltinInt::I32,
115-
Integer::I64 => BuiltinInt::I64,
116-
Integer::I128 => BuiltinInt::I128,
117-
}),
118-
false => BuiltinType::Uint(match size {
119-
Integer::I8 => BuiltinUint::U8,
120-
Integer::I16 => BuiltinUint::U16,
121-
Integer::I32 => BuiltinUint::U32,
122-
Integer::I64 => BuiltinUint::U64,
123-
Integer::I128 => BuiltinUint::U128,
124-
}),
125-
},
91+
let _p = tracing::info_span!("infer_query").entered();
92+
let resolver = def.resolver(db);
93+
let body = db.body(def);
94+
let mut ctx = InferenceContext::new(db, def, &body, resolver);
95+
96+
match def {
97+
DefWithBodyId::FunctionId(f) => {
98+
ctx.collect_fn(f);
99+
}
100+
DefWithBodyId::ConstId(c) => ctx.collect_const(c, &db.const_signature(c)),
101+
DefWithBodyId::StaticId(s) => ctx.collect_static(&db.static_signature(s)),
102+
DefWithBodyId::VariantId(v) => {
103+
ctx.return_ty = TyBuilder::builtin(
104+
match db.enum_signature(v.lookup(db).parent).variant_body_type() {
105+
hir_def::layout::IntegerType::Pointer(signed) => match signed {
106+
true => BuiltinType::Int(BuiltinInt::Isize),
107+
false => BuiltinType::Uint(BuiltinUint::Usize),
126108
},
127-
);
128-
}
109+
hir_def::layout::IntegerType::Fixed(size, signed) => match signed {
110+
true => BuiltinType::Int(match size {
111+
Integer::I8 => BuiltinInt::I8,
112+
Integer::I16 => BuiltinInt::I16,
113+
Integer::I32 => BuiltinInt::I32,
114+
Integer::I64 => BuiltinInt::I64,
115+
Integer::I128 => BuiltinInt::I128,
116+
}),
117+
false => BuiltinType::Uint(match size {
118+
Integer::I8 => BuiltinUint::U8,
119+
Integer::I16 => BuiltinUint::U16,
120+
Integer::I32 => BuiltinUint::U32,
121+
Integer::I64 => BuiltinUint::U64,
122+
Integer::I128 => BuiltinUint::U128,
123+
}),
124+
},
125+
},
126+
);
129127
}
128+
}
130129

131-
ctx.infer_body();
130+
ctx.infer_body();
132131

133-
ctx.infer_mut_body();
132+
ctx.infer_mut_body();
134133

135-
ctx.infer_closures();
134+
ctx.infer_closures();
136135

137-
Arc::new(ctx.resolve_all())
138-
})
136+
Arc::new(ctx.resolve_all())
139137
}
140138

141139
pub(crate) fn infer_cycle_result(_: &dyn HirDatabase, _: DefWithBodyId) -> Arc<InferenceResult> {

src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2168,9 +2168,7 @@ pub fn mir_body_query(db: &dyn HirDatabase, def: DefWithBodyId) -> Result<Arc<Mi
21682168
let _p = tracing::info_span!("mir_body_query", ?detail).entered();
21692169
let body = db.body(def);
21702170
let infer = db.infer(def);
2171-
let mut result = crate::next_solver::with_new_cache(|| {
2172-
lower_to_mir(db, def, &body, &infer, body.body_expr)
2173-
})?;
2171+
let mut result = lower_to_mir(db, def, &body, &infer, body.body_expr)?;
21742172
result.shrink_to_fit();
21752173
Ok(Arc::new(result))
21762174
}

src/tools/rust-analyzer/crates/hir-ty/src/next_solver/interner.rs

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2148,37 +2148,48 @@ TrivialTypeTraversalImpls! {
21482148
Placeholder<BoundVar>,
21492149
}
21502150

2151-
pub(crate) use tls_cache::with_new_cache;
21522151
mod tls_cache {
21532152
use crate::db::HirDatabase;
21542153

21552154
use super::DbInterner;
2155+
use base_db::Nonce;
21562156
use rustc_type_ir::search_graph::GlobalCache;
2157+
use salsa::Revision;
21572158
use std::cell::RefCell;
21582159

2159-
scoped_tls::scoped_thread_local!(static GLOBAL_CACHE: RefCell<rustc_type_ir::search_graph::GlobalCache<DbInterner<'static>>>);
2160+
struct Cache {
2161+
cache: GlobalCache<DbInterner<'static>>,
2162+
revision: Revision,
2163+
db_nonce: Nonce,
2164+
}
21602165

2161-
pub(crate) fn with_new_cache<T>(f: impl FnOnce() -> T) -> T {
2162-
GLOBAL_CACHE.set(&RefCell::new(GlobalCache::default()), f)
2166+
thread_local! {
2167+
static GLOBAL_CACHE: RefCell<Option<Cache>> = const { RefCell::new(None) };
21632168
}
21642169

21652170
pub(super) fn with_cache<'db, T>(
2166-
_db: &'db dyn HirDatabase,
2171+
db: &'db dyn HirDatabase,
21672172
f: impl FnOnce(&mut GlobalCache<DbInterner<'db>>) -> T,
21682173
) -> T {
2169-
// SAFETY: No idea
2170-
let call = move |slot: &RefCell<_>| {
2174+
GLOBAL_CACHE.with_borrow_mut(|handle| {
2175+
let (db_nonce, revision) = db.nonce_and_revision();
2176+
let handle = match handle {
2177+
Some(handle) => {
2178+
if handle.revision != revision || db_nonce != handle.db_nonce {
2179+
*handle = Cache { cache: GlobalCache::default(), revision, db_nonce };
2180+
}
2181+
handle
2182+
}
2183+
None => handle.insert(Cache { cache: GlobalCache::default(), revision, db_nonce }),
2184+
};
2185+
2186+
// SAFETY: No idea
21712187
f(unsafe {
21722188
std::mem::transmute::<
21732189
&mut GlobalCache<DbInterner<'static>>,
21742190
&mut GlobalCache<DbInterner<'db>>,
2175-
>(&mut *slot.borrow_mut())
2191+
>(&mut handle.cache)
21762192
})
2177-
};
2178-
if GLOBAL_CACHE.is_set() {
2179-
GLOBAL_CACHE.with(call)
2180-
} else {
2181-
GLOBAL_CACHE.set(&RefCell::new(GlobalCache::default()), || GLOBAL_CACHE.with(call))
2182-
}
2193+
})
21832194
}
21842195
}

src/tools/rust-analyzer/crates/hir-ty/src/test_db.rs

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
use std::{fmt, panic, sync::Mutex};
44

55
use base_db::{
6-
CrateGraphBuilder, CratesMap, FileSourceRootInput, FileText, RootQueryDb, SourceDatabase,
7-
SourceRoot, SourceRootId, SourceRootInput,
6+
CrateGraphBuilder, CratesMap, FileSourceRootInput, FileText, Nonce, RootQueryDb,
7+
SourceDatabase, SourceRoot, SourceRootId, SourceRootInput,
88
};
99

1010
use hir_def::{ModuleId, db::DefDatabase, nameres::crate_def_map};
@@ -17,12 +17,12 @@ use test_utils::extract_annotations;
1717
use triomphe::Arc;
1818

1919
#[salsa_macros::db]
20-
#[derive(Clone)]
2120
pub(crate) struct TestDB {
2221
storage: salsa::Storage<Self>,
2322
files: Arc<base_db::Files>,
2423
crates_map: Arc<CratesMap>,
2524
events: Arc<Mutex<Option<Vec<salsa::Event>>>>,
25+
nonce: Nonce,
2626
}
2727

2828
impl Default for TestDB {
@@ -41,6 +41,7 @@ impl Default for TestDB {
4141
events,
4242
files: Default::default(),
4343
crates_map: Default::default(),
44+
nonce: Nonce::new(),
4445
};
4546
this.set_expand_proc_attr_macros_with_durability(true, Durability::HIGH);
4647
// This needs to be here otherwise `CrateGraphBuilder` panics.
@@ -50,6 +51,18 @@ impl Default for TestDB {
5051
}
5152
}
5253

54+
impl Clone for TestDB {
55+
fn clone(&self) -> Self {
56+
Self {
57+
storage: self.storage.clone(),
58+
files: self.files.clone(),
59+
crates_map: self.crates_map.clone(),
60+
events: self.events.clone(),
61+
nonce: Nonce::new(),
62+
}
63+
}
64+
}
65+
5366
impl fmt::Debug for TestDB {
5467
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
5568
f.debug_struct("TestDB").finish()
@@ -109,6 +122,10 @@ impl SourceDatabase for TestDB {
109122
fn crates_map(&self) -> Arc<CratesMap> {
110123
self.crates_map.clone()
111124
}
125+
126+
fn nonce_and_revision(&self) -> (Nonce, salsa::Revision) {
127+
(self.nonce, salsa::plumbing::ZalsaDatabase::zalsa(self).current_revision())
128+
}
112129
}
113130

114131
#[salsa_macros::db]

src/tools/rust-analyzer/crates/ide-db/src/lib.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ use salsa::Durability;
5151
use std::{fmt, mem::ManuallyDrop};
5252

5353
use base_db::{
54-
CrateGraphBuilder, CratesMap, FileSourceRootInput, FileText, Files, RootQueryDb,
54+
CrateGraphBuilder, CratesMap, FileSourceRootInput, FileText, Files, Nonce, RootQueryDb,
5555
SourceDatabase, SourceRoot, SourceRootId, SourceRootInput, query_group,
5656
};
5757
use hir::{
@@ -83,6 +83,7 @@ pub struct RootDatabase {
8383
storage: ManuallyDrop<salsa::Storage<Self>>,
8484
files: Arc<Files>,
8585
crates_map: Arc<CratesMap>,
86+
nonce: Nonce,
8687
}
8788

8889
impl std::panic::RefUnwindSafe for RootDatabase {}
@@ -102,6 +103,7 @@ impl Clone for RootDatabase {
102103
storage: self.storage.clone(),
103104
files: self.files.clone(),
104105
crates_map: self.crates_map.clone(),
106+
nonce: Nonce::new(),
105107
}
106108
}
107109
}
@@ -165,6 +167,10 @@ impl SourceDatabase for RootDatabase {
165167
fn crates_map(&self) -> Arc<CratesMap> {
166168
self.crates_map.clone()
167169
}
170+
171+
fn nonce_and_revision(&self) -> (Nonce, salsa::Revision) {
172+
(self.nonce, salsa::plumbing::ZalsaDatabase::zalsa(self).current_revision())
173+
}
168174
}
169175

170176
impl Default for RootDatabase {
@@ -179,6 +185,7 @@ impl RootDatabase {
179185
storage: ManuallyDrop::new(salsa::Storage::default()),
180186
files: Default::default(),
181187
crates_map: Default::default(),
188+
nonce: Nonce::new(),
182189
};
183190
// This needs to be here otherwise `CrateGraphBuilder` will panic.
184191
db.set_all_crates(Arc::new(Box::new([])));

0 commit comments

Comments
 (0)