@@ -12,26 +12,30 @@ use crate::query::job::{report_cycle, QueryInfo, QueryJob, QueryJobId, QueryJobI
12
12
use crate :: query:: SerializedDepNodeIndex ;
13
13
use crate :: query:: { QueryContext , QueryMap , QuerySideEffects , QueryStackFrame } ;
14
14
use crate :: HandleCycleError ;
15
+ use hashbrown:: hash_table:: Entry ;
15
16
use 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 } ;
18
18
use rustc_data_structures:: stack:: ensure_sufficient_stack;
19
19
use rustc_data_structures:: sync:: Lock ;
20
20
#[ cfg( parallel_compiler) ]
21
21
use rustc_data_structures:: { outline, sync} ;
22
22
use rustc_errors:: { DiagnosticBuilder , FatalError , StashKey } ;
23
23
use rustc_span:: { Span , DUMMY_SP } ;
24
24
use std:: cell:: Cell ;
25
- use std:: collections:: hash_map:: Entry ;
26
25
use std:: fmt:: Debug ;
27
26
use std:: hash:: Hash ;
28
27
use std:: mem;
29
28
use thin_vec:: ThinVec ;
30
29
31
30
use super :: QueryConfig ;
32
31
32
+ #[ inline]
33
+ fn equivalent_key < K : Eq , V > ( k : & K ) -> impl Fn ( & ( K , V ) ) -> bool + ' _ {
34
+ move |x| x. 0 == * k
35
+ }
36
+
33
37
pub struct QueryState < K > {
34
- active : Sharded < FxHashMap < K , QueryResult > > ,
38
+ active : Sharded < hashbrown :: HashTable < ( K , QueryResult ) > > ,
35
39
}
36
40
37
41
/// Indicates the state of a query for a given key in a query map.
@@ -165,7 +169,7 @@ where
165
169
{
166
170
/// Completes the query by updating the query cache with the `result`,
167
171
/// 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 )
169
173
where
170
174
C : QueryCache < Key = K > ,
171
175
{
@@ -180,8 +184,11 @@ where
180
184
cache. complete ( key, result, dep_node_index) ;
181
185
182
186
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
+ }
185
192
} ;
186
193
187
194
job. signal_complete ( ) ;
@@ -198,11 +205,16 @@ where
198
205
// Poison the query so jobs waiting on it panic.
199
206
let state = self . state ;
200
207
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
+ }
206
218
} ;
207
219
// Also signal the completion of the job, so waiters
208
220
// will continue execution.
@@ -283,12 +295,11 @@ where
283
295
outline ( || {
284
296
// We didn't find the query result in the query cache. Check if it was
285
297
// 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 ( ) ,
292
303
_ => panic ! (
293
304
"query '{}' result must be in the cache or the query must be poisoned after a wait" ,
294
305
query. name( )
@@ -319,7 +330,8 @@ where
319
330
Qcx : QueryContext ,
320
331
{
321
332
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) ;
323
335
324
336
// For the parallel compiler we need to check both the query cache and query state structures
325
337
// while holding the state lock to ensure that 1) the query has not yet completed and 2) the
@@ -336,21 +348,21 @@ where
336
348
337
349
let current_job_id = qcx. current_query_job ( ) ;
338
350
339
- match state_lock. entry ( key) {
351
+ match state_lock. entry ( key_hash , equivalent_key ( & key) , | ( k , _ ) | sharded :: make_hash ( k ) ) {
340
352
Entry :: Vacant ( entry) => {
341
353
// Nothing has computed or is computing the query, so we start a new job and insert it in the
342
354
// state map.
343
355
let id = qcx. next_job_id ( ) ;
344
356
let job = QueryJob :: new ( id, span, current_job_id) ;
345
- entry. insert ( QueryResult :: Started ( job) ) ;
357
+ entry. insert ( ( key , QueryResult :: Started ( job) ) ) ;
346
358
347
359
// Drop the lock before we start executing the query
348
360
drop ( state_lock) ;
349
361
350
- execute_job :: < _ , _ , INCR > ( query, qcx, state, key, id, dep_node)
362
+ execute_job :: < _ , _ , INCR > ( query, qcx, state, key, key_hash , id, dep_node)
351
363
}
352
364
Entry :: Occupied ( mut entry) => {
353
- match entry. get_mut ( ) {
365
+ match & mut entry. get_mut ( ) . 1 {
354
366
QueryResult :: Started ( job) => {
355
367
#[ cfg( parallel_compiler) ]
356
368
if sync:: is_dyn_thread_safe ( ) {
@@ -382,6 +394,7 @@ fn execute_job<Q, Qcx, const INCR: bool>(
382
394
qcx : Qcx ,
383
395
state : & QueryState < Q :: Key > ,
384
396
key : Q :: Key ,
397
+ key_hash : u64 ,
385
398
id : QueryJobId ,
386
399
dep_node : Option < DepNode > ,
387
400
) -> ( Q :: Value , Option < DepNodeIndex > )
@@ -442,7 +455,7 @@ where
442
455
}
443
456
}
444
457
}
445
- job_owner. complete ( cache, result, dep_node_index) ;
458
+ job_owner. complete ( cache, key_hash , result, dep_node_index) ;
446
459
447
460
( result, Some ( dep_node_index) )
448
461
}
0 commit comments