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:: { outline, sync} ;
1615use rustc_errors:: { Diag , FatalError , StashKey } ;
@@ -25,8 +24,13 @@ use crate::query::caches::QueryCache;
2524use crate :: query:: job:: { QueryInfo , QueryJob , QueryJobId , QueryJobInfo , QueryLatch , report_cycle} ;
2625use crate :: query:: { QueryContext , QueryMap , QueryStackFrame , SerializedDepNodeIndex } ;
2726
27+ #[ inline]
28+ fn equivalent_key < K : Eq , V > ( k : & K ) -> impl Fn ( & ( K , V ) ) -> bool + ' _ {
29+ move |x| x. 0 == * k
30+ }
31+
2832pub struct QueryState < K > {
29- active : Sharded < FxHashMap < K , QueryResult > > ,
33+ active : Sharded < hashbrown :: HashTable < ( K , QueryResult ) > > ,
3034}
3135
3236/// Indicates the state of a query for a given key in a query map.
@@ -159,7 +163,7 @@ where
159163{
160164 /// Completes the query by updating the query cache with the `result`,
161165 /// signals the waiter and forgets the JobOwner, so it won't poison the query
162- fn complete < C > ( self , cache : & C , result : C :: Value , dep_node_index : DepNodeIndex )
166+ fn complete < C > ( self , cache : & C , key_hash : u64 , result : C :: Value , dep_node_index : DepNodeIndex )
163167 where
164168 C : QueryCache < Key = K > ,
165169 {
@@ -174,16 +178,17 @@ where
174178 cache. complete ( key, result, dep_node_index) ;
175179
176180 let job = {
177- let val = {
178- // don't keep the lock during the `unwrap()` of the retrieved value, or we taint the
179- // underlying shard.
180- // since unwinding also wants to look at this map, this can also prevent a double
181- // panic.
182- let mut lock = state . active . lock_shard_by_value ( & key) ;
183- lock . remove ( & key )
184- } ;
185- val . unwrap ( ) . expect_job ( )
181+ // don't keep the lock during the `unwrap()` of the retrieved value, or we taint the
182+ // underlying shard.
183+ // since unwinding also wants to look at this map, this can also prevent a double
184+ // panic.
185+ let mut shard = state . active . lock_shard_by_hash ( key_hash ) ;
186+ match shard . find_entry ( key_hash , equivalent_key ( & key) ) {
187+ Err ( _ ) => None ,
188+ Ok ( occupied ) => Some ( occupied . remove ( ) . 0 . 1 ) ,
189+ }
186190 } ;
191+ let job = job. expect ( "active query job entry" ) . expect_job ( ) ;
187192
188193 job. signal_complete ( ) ;
189194 }
@@ -199,11 +204,16 @@ where
199204 // Poison the query so jobs waiting on it panic.
200205 let state = self . state ;
201206 let job = {
202- let mut shard = state. active . lock_shard_by_value ( & self . key ) ;
203- let job = shard. remove ( & self . key ) . unwrap ( ) . expect_job ( ) ;
204-
205- shard. insert ( self . key , QueryResult :: Poisoned ) ;
206- job
207+ let key_hash = sharded:: make_hash ( & self . key ) ;
208+ let mut shard = state. active . lock_shard_by_hash ( key_hash) ;
209+ match shard. find_entry ( key_hash, equivalent_key ( & self . key ) ) {
210+ Err ( _) => panic ! ( ) ,
211+ Ok ( occupied) => {
212+ let ( ( key, value) , vacant) = occupied. remove ( ) ;
213+ vacant. insert ( ( key, QueryResult :: Poisoned ) ) ;
214+ value. expect_job ( )
215+ }
216+ }
207217 } ;
208218 // Also signal the completion of the job, so waiters
209219 // will continue execution.
@@ -283,11 +293,11 @@ where
283293 outline ( || {
284294 // We didn't find the query result in the query cache. Check if it was
285295 // 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) {
296+ let key_hash = sharded :: make_hash ( & key) ;
297+ let shard = query . query_state ( qcx ) . active . lock_shard_by_hash ( key_hash ) ;
298+ match shard . find ( key_hash , equivalent_key ( & key) ) {
289299 // The query we waited on panicked. Continue unwinding here.
290- Some ( QueryResult :: Poisoned ) => FatalError . raise ( ) ,
300+ Some ( ( _ , QueryResult :: Poisoned ) ) => FatalError . raise ( ) ,
291301 _ => panic ! (
292302 "query '{}' result must be in the cache or the query must be poisoned after a wait" ,
293303 query. name( )
@@ -318,7 +328,8 @@ where
318328 Qcx : QueryContext ,
319329{
320330 let state = query. query_state ( qcx) ;
321- let mut state_lock = state. active . lock_shard_by_value ( & key) ;
331+ let key_hash = sharded:: make_hash ( & key) ;
332+ let mut state_lock = state. active . lock_shard_by_hash ( key_hash) ;
322333
323334 // For the parallel compiler we need to check both the query cache and query state structures
324335 // while holding the state lock to ensure that 1) the query has not yet completed and 2) the
@@ -335,21 +346,21 @@ where
335346
336347 let current_job_id = qcx. current_query_job ( ) ;
337348
338- match state_lock. entry ( key) {
349+ match state_lock. entry ( key_hash , equivalent_key ( & key) , | ( k , _ ) | sharded :: make_hash ( k ) ) {
339350 Entry :: Vacant ( entry) => {
340351 // Nothing has computed or is computing the query, so we start a new job and insert it in the
341352 // state map.
342353 let id = qcx. next_job_id ( ) ;
343354 let job = QueryJob :: new ( id, span, current_job_id) ;
344- entry. insert ( QueryResult :: Started ( job) ) ;
355+ entry. insert ( ( key , QueryResult :: Started ( job) ) ) ;
345356
346357 // Drop the lock before we start executing the query
347358 drop ( state_lock) ;
348359
349- execute_job :: < _ , _ , INCR > ( query, qcx, state, key, id, dep_node)
360+ execute_job :: < _ , _ , INCR > ( query, qcx, state, key, key_hash , id, dep_node)
350361 }
351362 Entry :: Occupied ( mut entry) => {
352- match entry. get_mut ( ) {
363+ match & mut entry. get_mut ( ) . 1 {
353364 QueryResult :: Started ( job) => {
354365 if sync:: is_dyn_thread_safe ( ) {
355366 // Get the latch out
@@ -380,6 +391,7 @@ fn execute_job<Q, Qcx, const INCR: bool>(
380391 qcx : Qcx ,
381392 state : & QueryState < Q :: Key > ,
382393 key : Q :: Key ,
394+ key_hash : u64 ,
383395 id : QueryJobId ,
384396 dep_node : Option < DepNode > ,
385397) -> ( Q :: Value , Option < DepNodeIndex > )
@@ -440,7 +452,7 @@ where
440452 }
441453 }
442454 }
443- job_owner. complete ( cache, result, dep_node_index) ;
455+ job_owner. complete ( cache, key_hash , result, dep_node_index) ;
444456
445457 ( result, Some ( dep_node_index) )
446458}
0 commit comments