3
3
//! manage the caches, and so forth.
4
4
5
5
use std:: cell:: Cell ;
6
- use std:: collections:: hash_map:: Entry ;
7
6
use std:: fmt:: Debug ;
8
7
use std:: hash:: Hash ;
9
8
use std:: mem;
10
9
10
+ use hashbrown:: hash_table:: Entry ;
11
11
use 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 } ;
14
13
use rustc_data_structures:: stack:: ensure_sufficient_stack;
15
14
use rustc_data_structures:: { outline, sync} ;
16
15
use rustc_errors:: { Diag , FatalError , StashKey } ;
@@ -25,8 +24,13 @@ use crate::query::caches::QueryCache;
25
24
use crate :: query:: job:: { QueryInfo , QueryJob , QueryJobId , QueryJobInfo , QueryLatch , report_cycle} ;
26
25
use crate :: query:: { QueryContext , QueryMap , QueryStackFrame , SerializedDepNodeIndex } ;
27
26
27
+ #[ inline]
28
+ fn equivalent_key < K : Eq , V > ( k : & K ) -> impl Fn ( & ( K , V ) ) -> bool + ' _ {
29
+ move |x| x. 0 == * k
30
+ }
31
+
28
32
pub struct QueryState < K > {
29
- active : Sharded < FxHashMap < K , QueryResult > > ,
33
+ active : Sharded < hashbrown :: HashTable < ( K , QueryResult ) > > ,
30
34
}
31
35
32
36
/// Indicates the state of a query for a given key in a query map.
@@ -159,7 +163,7 @@ where
159
163
{
160
164
/// Completes the query by updating the query cache with the `result`,
161
165
/// 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 )
163
167
where
164
168
C : QueryCache < Key = K > ,
165
169
{
@@ -174,16 +178,17 @@ where
174
178
cache. complete ( key, result, dep_node_index) ;
175
179
176
180
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
+ }
186
190
} ;
191
+ let job = job. expect ( "active query job entry" ) . expect_job ( ) ;
187
192
188
193
job. signal_complete ( ) ;
189
194
}
@@ -199,11 +204,16 @@ where
199
204
// Poison the query so jobs waiting on it panic.
200
205
let state = self . state ;
201
206
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
+ }
207
217
} ;
208
218
// Also signal the completion of the job, so waiters
209
219
// will continue execution.
@@ -283,11 +293,11 @@ where
283
293
outline ( || {
284
294
// We didn't find the query result in the query cache. Check if it was
285
295
// 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) ) {
289
299
// The query we waited on panicked. Continue unwinding here.
290
- Some ( QueryResult :: Poisoned ) => FatalError . raise ( ) ,
300
+ Some ( ( _ , QueryResult :: Poisoned ) ) => FatalError . raise ( ) ,
291
301
_ => panic ! (
292
302
"query '{}' result must be in the cache or the query must be poisoned after a wait" ,
293
303
query. name( )
@@ -318,7 +328,8 @@ where
318
328
Qcx : QueryContext ,
319
329
{
320
330
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) ;
322
333
323
334
// For the parallel compiler we need to check both the query cache and query state structures
324
335
// while holding the state lock to ensure that 1) the query has not yet completed and 2) the
@@ -335,21 +346,21 @@ where
335
346
336
347
let current_job_id = qcx. current_query_job ( ) ;
337
348
338
- match state_lock. entry ( key) {
349
+ match state_lock. entry ( key_hash , equivalent_key ( & key) , | ( k , _ ) | sharded :: make_hash ( k ) ) {
339
350
Entry :: Vacant ( entry) => {
340
351
// Nothing has computed or is computing the query, so we start a new job and insert it in the
341
352
// state map.
342
353
let id = qcx. next_job_id ( ) ;
343
354
let job = QueryJob :: new ( id, span, current_job_id) ;
344
- entry. insert ( QueryResult :: Started ( job) ) ;
355
+ entry. insert ( ( key , QueryResult :: Started ( job) ) ) ;
345
356
346
357
// Drop the lock before we start executing the query
347
358
drop ( state_lock) ;
348
359
349
- execute_job :: < _ , _ , INCR > ( query, qcx, state, key, id, dep_node)
360
+ execute_job :: < _ , _ , INCR > ( query, qcx, state, key, key_hash , id, dep_node)
350
361
}
351
362
Entry :: Occupied ( mut entry) => {
352
- match entry. get_mut ( ) {
363
+ match & mut entry. get_mut ( ) . 1 {
353
364
QueryResult :: Started ( job) => {
354
365
if sync:: is_dyn_thread_safe ( ) {
355
366
// Get the latch out
@@ -380,6 +391,7 @@ fn execute_job<Q, Qcx, const INCR: bool>(
380
391
qcx : Qcx ,
381
392
state : & QueryState < Q :: Key > ,
382
393
key : Q :: Key ,
394
+ key_hash : u64 ,
383
395
id : QueryJobId ,
384
396
dep_node : Option < DepNode > ,
385
397
) -> ( Q :: Value , Option < DepNodeIndex > )
@@ -440,7 +452,7 @@ where
440
452
}
441
453
}
442
454
}
443
- job_owner. complete ( cache, result, dep_node_index) ;
455
+ job_owner. complete ( cache, key_hash , result, dep_node_index) ;
444
456
445
457
( result, Some ( dep_node_index) )
446
458
}
0 commit comments