@@ -12,26 +12,30 @@ use crate::query::job::{report_cycle, QueryInfo, QueryJob, QueryJobId, QueryJobI
1212use crate :: query:: SerializedDepNodeIndex ;
1313use crate :: query:: { QueryContext , QueryMap , QuerySideEffects , QueryStackFrame } ;
1414use crate :: HandleCycleError ;
15+ use hashbrown:: hash_table:: Entry ;
1516use rustc_data_structures:: fingerprint:: Fingerprint ;
16- use rustc_data_structures:: fx:: FxHashMap ;
17- use rustc_data_structures:: sharded:: Sharded ;
17+ use rustc_data_structures:: sharded:: { self , Sharded } ;
1818use rustc_data_structures:: stack:: ensure_sufficient_stack;
1919use rustc_data_structures:: sync:: Lock ;
2020#[ cfg( parallel_compiler) ]
2121use rustc_data_structures:: { outline, sync} ;
2222use rustc_errors:: { DiagnosticBuilder , FatalError , StashKey } ;
2323use rustc_span:: { Span , DUMMY_SP } ;
2424use std:: cell:: Cell ;
25- use std:: collections:: hash_map:: Entry ;
2625use std:: fmt:: Debug ;
2726use std:: hash:: Hash ;
2827use std:: mem;
2928use thin_vec:: ThinVec ;
3029
3130use super :: QueryConfig ;
3231
32+ #[ inline]
33+ fn equivalent_key < K : Eq , V > ( k : & K ) -> impl Fn ( & ( K , V ) ) -> bool + ' _ {
34+ move |x| x. 0 == * k
35+ }
36+
3337pub struct QueryState < K > {
34- active : Sharded < FxHashMap < K , QueryResult > > ,
38+ active : Sharded < hashbrown :: HashTable < ( K , QueryResult ) > > ,
3539}
3640
3741/// Indicates the state of a query for a given key in a query map.
@@ -165,7 +169,7 @@ where
165169{
166170 /// Completes the query by updating the query cache with the `result`,
167171 /// signals the waiter and forgets the JobOwner, so it won't poison the query
168- fn complete < C > ( self , cache : & C , result : C :: Value , dep_node_index : DepNodeIndex )
172+ fn complete < C > ( self , cache : & C , key_hash : u64 , result : C :: Value , dep_node_index : DepNodeIndex )
169173 where
170174 C : QueryCache < Key = K > ,
171175 {
@@ -180,8 +184,11 @@ where
180184 cache. complete ( key, result, dep_node_index) ;
181185
182186 let job = {
183- let mut lock = state. active . lock_shard_by_value ( & key) ;
184- lock. remove ( & key) . unwrap ( ) . expect_job ( )
187+ let mut shard = state. active . lock_shard_by_hash ( key_hash) ;
188+ match shard. find_entry ( key_hash, equivalent_key ( & key) ) {
189+ Err ( _) => panic ! ( ) ,
190+ Ok ( occupied) => occupied. remove ( ) . 0 . 1 . expect_job ( ) ,
191+ }
185192 } ;
186193
187194 job. signal_complete ( ) ;
@@ -198,11 +205,16 @@ where
198205 // Poison the query so jobs waiting on it panic.
199206 let state = self . state ;
200207 let job = {
201- let mut shard = state. active . lock_shard_by_value ( & self . key ) ;
202- let job = shard. remove ( & self . key ) . unwrap ( ) . expect_job ( ) ;
203-
204- shard. insert ( self . key , QueryResult :: Poisoned ) ;
205- job
208+ let key_hash = sharded:: make_hash ( & self . key ) ;
209+ let mut shard = state. active . lock_shard_by_hash ( key_hash) ;
210+ match shard. find_entry ( key_hash, equivalent_key ( & self . key ) ) {
211+ Err ( _) => panic ! ( ) ,
212+ Ok ( occupied) => {
213+ let ( ( key, value) , vacant) = occupied. remove ( ) ;
214+ vacant. insert ( ( key, QueryResult :: Poisoned ) ) ;
215+ value. expect_job ( )
216+ }
217+ }
206218 } ;
207219 // Also signal the completion of the job, so waiters
208220 // will continue execution.
@@ -283,12 +295,11 @@ where
283295 outline ( || {
284296 // We didn't find the query result in the query cache. Check if it was
285297 // poisoned due to a panic instead.
286- let lock = query. query_state ( qcx) . active . get_shard_by_value ( & key) . lock ( ) ;
287-
288- match lock. get ( & key) {
289- Some ( QueryResult :: Poisoned ) => {
290- panic ! ( "query '{}' not cached due to poisoning" , query. name( ) )
291- }
298+ let key_hash = sharded:: make_hash ( & key) ;
299+ let shard = query. query_state ( qcx) . active . lock_shard_by_hash ( key_hash) ;
300+ match shard. find ( key_hash, equivalent_key ( & key) ) {
301+ // The query we waited on panicked. Continue unwinding here.
302+ Some ( ( _, QueryResult :: Poisoned ) ) => FatalError . raise ( ) ,
292303 _ => panic ! (
293304 "query '{}' result must be in the cache or the query must be poisoned after a wait" ,
294305 query. name( )
@@ -319,7 +330,8 @@ where
319330 Qcx : QueryContext ,
320331{
321332 let state = query. query_state ( qcx) ;
322- let mut state_lock = state. active . lock_shard_by_value ( & key) ;
333+ let key_hash = sharded:: make_hash ( & key) ;
334+ let mut state_lock = state. active . lock_shard_by_hash ( key_hash) ;
323335
324336 // For the parallel compiler we need to check both the query cache and query state structures
325337 // while holding the state lock to ensure that 1) the query has not yet completed and 2) the
@@ -336,21 +348,21 @@ where
336348
337349 let current_job_id = qcx. current_query_job ( ) ;
338350
339- match state_lock. entry ( key) {
351+ match state_lock. entry ( key_hash , equivalent_key ( & key) , | ( k , _ ) | sharded :: make_hash ( k ) ) {
340352 Entry :: Vacant ( entry) => {
341353 // Nothing has computed or is computing the query, so we start a new job and insert it in the
342354 // state map.
343355 let id = qcx. next_job_id ( ) ;
344356 let job = QueryJob :: new ( id, span, current_job_id) ;
345- entry. insert ( QueryResult :: Started ( job) ) ;
357+ entry. insert ( ( key , QueryResult :: Started ( job) ) ) ;
346358
347359 // Drop the lock before we start executing the query
348360 drop ( state_lock) ;
349361
350- execute_job :: < _ , _ , INCR > ( query, qcx, state, key, id, dep_node)
362+ execute_job :: < _ , _ , INCR > ( query, qcx, state, key, key_hash , id, dep_node)
351363 }
352364 Entry :: Occupied ( mut entry) => {
353- match entry. get_mut ( ) {
365+ match & mut entry. get_mut ( ) . 1 {
354366 QueryResult :: Started ( job) => {
355367 #[ cfg( parallel_compiler) ]
356368 if sync:: is_dyn_thread_safe ( ) {
@@ -382,6 +394,7 @@ fn execute_job<Q, Qcx, const INCR: bool>(
382394 qcx : Qcx ,
383395 state : & QueryState < Q :: Key > ,
384396 key : Q :: Key ,
397+ key_hash : u64 ,
385398 id : QueryJobId ,
386399 dep_node : Option < DepNode > ,
387400) -> ( Q :: Value , Option < DepNodeIndex > )
@@ -442,7 +455,7 @@ where
442455 }
443456 }
444457 }
445- job_owner. complete ( cache, result, dep_node_index) ;
458+ job_owner. complete ( cache, key_hash , result, dep_node_index) ;
446459
447460 ( result, Some ( dep_node_index) )
448461}
0 commit comments