@@ -2,8 +2,11 @@ use crate::dep_graph::DepNodeIndex;
2
2
3
3
use rustc_data_structures:: fx:: FxHashMap ;
4
4
use rustc_data_structures:: sharded:: { self , Sharded } ;
5
- use rustc_data_structures:: sync:: OnceLock ;
5
+ use rustc_data_structures:: sync:: { Lock , OnceLock } ;
6
+ use rustc_hir:: def_id:: LOCAL_CRATE ;
6
7
use rustc_index:: { Idx , IndexVec } ;
8
+ use rustc_span:: def_id:: DefId ;
9
+ use rustc_span:: def_id:: DefIndex ;
7
10
use std:: fmt:: Debug ;
8
11
use std:: hash:: Hash ;
9
12
use std:: marker:: PhantomData ;
@@ -148,6 +151,8 @@ where
148
151
149
152
#[ inline( always) ]
150
153
fn lookup ( & self , key : & K ) -> Option < ( V , DepNodeIndex ) > {
154
+ // FIXME: lock_shard_by_hash will use high bits which are usually zero in the index() passed
155
+ // here. This makes sharding essentially useless, always selecting the zero'th shard.
151
156
let lock = self . cache . lock_shard_by_hash ( key. index ( ) as u64 ) ;
152
157
if let Some ( Some ( value) ) = lock. get ( * key) { Some ( * value) } else { None }
153
158
}
@@ -168,3 +173,75 @@ where
168
173
}
169
174
}
170
175
}
176
+
177
+ pub struct DefIdCacheSelector ;
178
+
179
+ impl < ' tcx , V : ' tcx > CacheSelector < ' tcx , V > for DefIdCacheSelector {
180
+ type Cache = DefIdCache < V >
181
+ where
182
+ V : Copy ;
183
+ }
184
+
185
+ pub struct DefIdCache < V > {
186
+ /// Stores the local DefIds in a dense map. Local queries are much more often dense, so this is
187
+ /// a win over hashing query keys at marginal memory cost (~5% at most) compared to FxHashMap.
188
+ ///
189
+ /// The second element of the tuple is the set of keys actually present in the IndexVec, used
190
+ /// for faster iteration in `iter()`.
191
+ // FIXME: This may want to be sharded, like VecCache. However *how* to shard an IndexVec isn't
192
+ // super clear; VecCache is effectively not sharded today (see FIXME there). For now just omit
193
+ // that complexity here.
194
+ local : Lock < ( IndexVec < DefIndex , Option < ( V , DepNodeIndex ) > > , Vec < DefIndex > ) > ,
195
+ foreign : DefaultCache < DefId , V > ,
196
+ }
197
+
198
+ impl < V > Default for DefIdCache < V > {
199
+ fn default ( ) -> Self {
200
+ DefIdCache { local : Default :: default ( ) , foreign : Default :: default ( ) }
201
+ }
202
+ }
203
+
204
+ impl < V > QueryCache for DefIdCache < V >
205
+ where
206
+ V : Copy ,
207
+ {
208
+ type Key = DefId ;
209
+ type Value = V ;
210
+
211
+ #[ inline( always) ]
212
+ fn lookup ( & self , key : & DefId ) -> Option < ( V , DepNodeIndex ) > {
213
+ if key. krate == LOCAL_CRATE {
214
+ let cache = self . local . lock ( ) ;
215
+ cache. 0 . get ( key. index ) . and_then ( |v| * v)
216
+ } else {
217
+ self . foreign . lookup ( key)
218
+ }
219
+ }
220
+
221
+ #[ inline]
222
+ fn complete ( & self , key : DefId , value : V , index : DepNodeIndex ) {
223
+ if key. krate == LOCAL_CRATE {
224
+ let mut cache = self . local . lock ( ) ;
225
+ let ( cache, present) = & mut * cache;
226
+ let slot = cache. ensure_contains_elem ( key. index , Default :: default) ;
227
+ if slot. is_none ( ) {
228
+ // FIXME: Only store the present set when running in incremental mode. `iter` is not
229
+ // used outside of saving caches to disk and self-profile.
230
+ present. push ( key. index ) ;
231
+ }
232
+ * slot = Some ( ( value, index) ) ;
233
+ } else {
234
+ self . foreign . complete ( key, value, index)
235
+ }
236
+ }
237
+
238
+ fn iter ( & self , f : & mut dyn FnMut ( & Self :: Key , & Self :: Value , DepNodeIndex ) ) {
239
+ let guard = self . local . lock ( ) ;
240
+ let ( cache, present) = & * guard;
241
+ for & idx in present. iter ( ) {
242
+ let value = cache[ idx] . unwrap ( ) ;
243
+ f ( & DefId { krate : LOCAL_CRATE , index : idx } , & value. 0 , value. 1 ) ;
244
+ }
245
+ self . foreign . iter ( f) ;
246
+ }
247
+ }
0 commit comments