11use std:: fmt:: Debug ;
22use std:: hash:: Hash ;
3- use std:: sync:: OnceLock ;
3+ use std:: sync:: { Mutex , OnceLock } ;
44
55use rustc_data_structures:: sharded:: ShardedHashMap ;
66pub use rustc_data_structures:: vec_cache:: VecCache ;
@@ -23,6 +23,17 @@ pub trait QueryCache: Sized {
2323 /// given key, if it is present in the cache.
2424 fn lookup ( & self , key : & Self :: Key ) -> Option < ( Self :: Value , DepNodeIndex ) > ;
2525
26+ /// Start the job.
27+ ///
28+ /// After the first call to `to_unique_index`, the returned index is guaranteed to be
29+ /// uniquely bound to `key` until earlier of `drop(self)` or `complete(key, ...)`.
30+ fn to_unique_index ( & self , key : & Self :: Key ) -> usize ;
31+
32+ /// Reverse the mapping of to_unique_index to a key.
33+ ///
34+ /// Will panic if called with an index that's not currently available.
35+ fn to_key ( & self , idx : usize ) -> Self :: Key ;
36+
2637 /// Adds a key/value entry to this cache.
2738 ///
2839 /// Called by some part of the query system, after having obtained the
@@ -36,11 +47,12 @@ pub trait QueryCache: Sized {
3647/// more specialized kinds of cache. Backed by a sharded hashmap.
3748pub struct DefaultCache < K , V > {
3849 cache : ShardedHashMap < K , ( V , DepNodeIndex ) > ,
50+ active : Mutex < Vec < Option < K > > > ,
3951}
4052
4153impl < K , V > Default for DefaultCache < K , V > {
4254 fn default ( ) -> Self {
43- DefaultCache { cache : Default :: default ( ) }
55+ DefaultCache { cache : Default :: default ( ) , active : Default :: default ( ) }
4456 }
4557}
4658
@@ -57,11 +69,49 @@ where
5769 self . cache . get ( key)
5870 }
5971
72+ fn to_unique_index ( & self , key : & Self :: Key ) -> usize {
73+ let mut guard = self . active . lock ( ) . unwrap ( ) ;
74+
75+ for ( idx, slot) in guard. iter_mut ( ) . enumerate ( ) {
76+ if let Some ( k) = slot
77+ && k == key
78+ {
79+ // Return idx if we found the slot containing this key.
80+ return idx;
81+ } else if slot. is_none ( ) {
82+ // If slot is empty, reuse it.
83+ * slot = Some ( * key) ;
84+ return idx;
85+ }
86+ }
87+
88+ // If no slot currently contains our key, add a new slot.
89+ let idx = guard. len ( ) ;
90+ guard. push ( Some ( * key) ) ;
91+ return idx;
92+ }
93+
94+ fn to_key ( & self , idx : usize ) -> Self :: Key {
95+ let guard = self . active . lock ( ) . unwrap ( ) ;
96+ guard[ idx] . expect ( "still present" )
97+ }
98+
6099 #[ inline]
61100 fn complete ( & self , key : K , value : V , index : DepNodeIndex ) {
62101 // We may be overwriting another value. This is all right, since the dep-graph
63102 // will check that the fingerprint matches.
64103 self . cache . insert ( key, ( value, index) ) ;
104+
105+ // Make sure to do this second -- this ensures lookups return success prior to active
106+ // getting removed, helping avoiding assignment of multiple indices per logical key.
107+ let mut guard = self . active . lock ( ) . unwrap ( ) ;
108+ for slot in guard. iter_mut ( ) {
109+ if let Some ( k) = slot
110+ && * k == key
111+ {
112+ * slot = None ;
113+ }
114+ }
65115 }
66116
67117 fn iter ( & self , f : & mut dyn FnMut ( & Self :: Key , & Self :: Value , DepNodeIndex ) ) {
@@ -102,6 +152,15 @@ where
102152 self . cache . set ( ( value, index) ) . ok ( ) ;
103153 }
104154
155+ fn to_unique_index ( & self , _: & Self :: Key ) -> usize {
156+ // SingleCache has a single key, so we can map directly to a constant.
157+ 0
158+ }
159+
160+ fn to_key ( & self , _: usize ) -> Self :: Key {
161+ ( )
162+ }
163+
105164 fn iter ( & self , f : & mut dyn FnMut ( & Self :: Key , & Self :: Value , DepNodeIndex ) ) {
106165 if let Some ( value) = self . cache . get ( ) {
107166 f ( & ( ) , & value. 0 , value. 1 )
@@ -142,6 +201,32 @@ where
142201 }
143202 }
144203
204+ fn to_unique_index ( & self , key : & Self :: Key ) -> usize {
205+ if key. krate == LOCAL_CRATE {
206+ // The local cache assigns keys based on allocated addresses in the backing VecCache.
207+ //
208+ // Those addresses are always at least 4-aligned (due to DepNodeIndex), so the low bit
209+ // can't be set. This means these don't overlap with the other cache given we |1 those
210+ // IDs. We check this with the assertion.
211+ let local_idx = self . local . to_unique_index ( & key. index ) ;
212+ assert ! ( local_idx & 1 == 0 ) ;
213+ local_idx
214+ } else {
215+ // Shifting is safe because DefaultCache uses only u32 for its indices, so we won't
216+ // overflow here.
217+ ( self . foreign . to_unique_index ( key) << 1 ) | 1
218+ }
219+ }
220+
221+ fn to_key ( & self , idx : usize ) -> Self :: Key {
222+ if idx & 1 == 0 {
223+ // local
224+ DefId :: local ( self . local . to_key ( idx) )
225+ } else {
226+ self . foreign . to_key ( idx >> 1 )
227+ }
228+ }
229+
145230 #[ inline]
146231 fn complete ( & self , key : DefId , value : V , index : DepNodeIndex ) {
147232 if key. krate == LOCAL_CRATE {
@@ -180,4 +265,12 @@ where
180265 fn iter ( & self , f : & mut dyn FnMut ( & Self :: Key , & Self :: Value , DepNodeIndex ) ) {
181266 self . iter ( f)
182267 }
268+
269+ fn to_unique_index ( & self , key : & Self :: Key ) -> usize {
270+ self . to_slot_address ( key)
271+ }
272+
273+ fn to_key ( & self , idx : usize ) -> Self :: Key {
274+ self . to_key ( idx)
275+ }
183276}
0 commit comments