33//! manage the caches, and so forth.
44
55use std:: cell:: Cell ;
6- use std:: collections:: hash_map:: Entry ;
76use std:: fmt:: Debug ;
87use std:: hash:: Hash ;
98use std:: mem;
109
10+ use hashbrown:: hash_table:: Entry ;
1111use rustc_data_structures:: fingerprint:: Fingerprint ;
12- use rustc_data_structures:: fx:: FxHashMap ;
13- use rustc_data_structures:: sharded:: Sharded ;
12+ use rustc_data_structures:: sharded:: { self , Sharded } ;
1413use rustc_data_structures:: stack:: ensure_sufficient_stack;
1514use rustc_data_structures:: sync:: Lock ;
1615use rustc_data_structures:: { outline, sync} ;
@@ -29,8 +28,13 @@ use crate::query::{
2928 QueryContext , QueryMap , QuerySideEffects , QueryStackFrame , SerializedDepNodeIndex ,
3029} ;
3130
31+ #[ inline]
32+ fn equivalent_key < K : Eq , V > ( k : & K ) -> impl Fn ( & ( K , V ) ) -> bool + ' _ {
33+ move |x| x. 0 == * k
34+ }
35+
3236pub struct QueryState < K > {
33- active : Sharded < FxHashMap < K , QueryResult > > ,
37+ active : Sharded < hashbrown :: HashTable < ( K , QueryResult ) > > ,
3438}
3539
3640/// Indicates the state of a query for a given key in a query map.
@@ -163,7 +167,7 @@ where
163167{
164168 /// Completes the query by updating the query cache with the `result`,
165169 /// signals the waiter and forgets the JobOwner, so it won't poison the query
166- fn complete < C > ( self , cache : & C , result : C :: Value , dep_node_index : DepNodeIndex )
170+ fn complete < C > ( self , cache : & C , key_hash : u64 , result : C :: Value , dep_node_index : DepNodeIndex )
167171 where
168172 C : QueryCache < Key = K > ,
169173 {
@@ -178,16 +182,17 @@ where
178182 cache. complete ( key, result, dep_node_index) ;
179183
180184 let job = {
181- let val = {
182- // don't keep the lock during the `unwrap()` of the retrieved value, or we taint the
183- // underlying shard.
184- // since unwinding also wants to look at this map, this can also prevent a double
185- // panic.
186- let mut lock = state . active . lock_shard_by_value ( & key) ;
187- lock . remove ( & key )
188- } ;
189- val . unwrap ( ) . expect_job ( )
185+ // don't keep the lock during the `unwrap()` of the retrieved value, or we taint the
186+ // underlying shard.
187+ // since unwinding also wants to look at this map, this can also prevent a double
188+ // panic.
189+ let mut shard = state . active . lock_shard_by_hash ( key_hash ) ;
190+ match shard . find_entry ( key_hash , equivalent_key ( & key) ) {
191+ Err ( _ ) => None ,
192+ Ok ( occupied ) => Some ( occupied . remove ( ) . 0 . 1 ) ,
193+ }
190194 } ;
195+ let job = job. expect ( "active query job entry" ) . expect_job ( ) ;
191196
192197 job. signal_complete ( ) ;
193198 }
@@ -203,11 +208,16 @@ where
203208 // Poison the query so jobs waiting on it panic.
204209 let state = self . state ;
205210 let job = {
206- let mut shard = state. active . lock_shard_by_value ( & self . key ) ;
207- let job = shard. remove ( & self . key ) . unwrap ( ) . expect_job ( ) ;
208-
209- shard. insert ( self . key , QueryResult :: Poisoned ) ;
210- job
211+ let key_hash = sharded:: make_hash ( & self . key ) ;
212+ let mut shard = state. active . lock_shard_by_hash ( key_hash) ;
213+ match shard. find_entry ( key_hash, equivalent_key ( & self . key ) ) {
214+ Err ( _) => panic ! ( ) ,
215+ Ok ( occupied) => {
216+ let ( ( key, value) , vacant) = occupied. remove ( ) ;
217+ vacant. insert ( ( key, QueryResult :: Poisoned ) ) ;
218+ value. expect_job ( )
219+ }
220+ }
211221 } ;
212222 // Also signal the completion of the job, so waiters
213223 // will continue execution.
@@ -287,11 +297,11 @@ where
287297 outline ( || {
288298 // We didn't find the query result in the query cache. Check if it was
289299 // poisoned due to a panic instead.
290- let lock = query . query_state ( qcx ) . active . get_shard_by_value ( & key) . lock ( ) ;
291-
292- match lock . get ( & key) {
300+ let key_hash = sharded :: make_hash ( & key) ;
301+ let shard = query . query_state ( qcx ) . active . lock_shard_by_hash ( key_hash ) ;
302+ match shard . find ( key_hash , equivalent_key ( & key) ) {
293303 // The query we waited on panicked. Continue unwinding here.
294- Some ( QueryResult :: Poisoned ) => FatalError . raise ( ) ,
304+ Some ( ( _ , QueryResult :: Poisoned ) ) => FatalError . raise ( ) ,
295305 _ => panic ! (
296306 "query '{}' result must be in the cache or the query must be poisoned after a wait" ,
297307 query. name( )
@@ -322,7 +332,8 @@ where
322332 Qcx : QueryContext ,
323333{
324334 let state = query. query_state ( qcx) ;
325- let mut state_lock = state. active . lock_shard_by_value ( & key) ;
335+ let key_hash = sharded:: make_hash ( & key) ;
336+ let mut state_lock = state. active . lock_shard_by_hash ( key_hash) ;
326337
327338 // For the parallel compiler we need to check both the query cache and query state structures
328339 // while holding the state lock to ensure that 1) the query has not yet completed and 2) the
@@ -339,21 +350,21 @@ where
339350
340351 let current_job_id = qcx. current_query_job ( ) ;
341352
342- match state_lock. entry ( key) {
353+ match state_lock. entry ( key_hash , equivalent_key ( & key) , | ( k , _ ) | sharded :: make_hash ( k ) ) {
343354 Entry :: Vacant ( entry) => {
344355 // Nothing has computed or is computing the query, so we start a new job and insert it in the
345356 // state map.
346357 let id = qcx. next_job_id ( ) ;
347358 let job = QueryJob :: new ( id, span, current_job_id) ;
348- entry. insert ( QueryResult :: Started ( job) ) ;
359+ entry. insert ( ( key , QueryResult :: Started ( job) ) ) ;
349360
350361 // Drop the lock before we start executing the query
351362 drop ( state_lock) ;
352363
353- execute_job :: < _ , _ , INCR > ( query, qcx, state, key, id, dep_node)
364+ execute_job :: < _ , _ , INCR > ( query, qcx, state, key, key_hash , id, dep_node)
354365 }
355366 Entry :: Occupied ( mut entry) => {
356- match entry. get_mut ( ) {
367+ match & mut entry. get_mut ( ) . 1 {
357368 QueryResult :: Started ( job) => {
358369 if sync:: is_dyn_thread_safe ( ) {
359370 // Get the latch out
@@ -384,6 +395,7 @@ fn execute_job<Q, Qcx, const INCR: bool>(
384395 qcx : Qcx ,
385396 state : & QueryState < Q :: Key > ,
386397 key : Q :: Key ,
398+ key_hash : u64 ,
387399 id : QueryJobId ,
388400 dep_node : Option < DepNode > ,
389401) -> ( Q :: Value , Option < DepNodeIndex > )
@@ -444,7 +456,7 @@ where
444456 }
445457 }
446458 }
447- job_owner. complete ( cache, result, dep_node_index) ;
459+ job_owner. complete ( cache, key_hash , result, dep_node_index) ;
448460
449461 ( result, Some ( dep_node_index) )
450462}
0 commit comments