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:: sync:: Lock ;
16
15
use rustc_data_structures:: { outline, sync} ;
@@ -29,8 +28,13 @@ use crate::query::{
29
28
QueryContext , QueryMap , QuerySideEffects , QueryStackFrame , SerializedDepNodeIndex ,
30
29
} ;
31
30
31
+ #[ inline]
32
+ fn equivalent_key < K : Eq , V > ( k : & K ) -> impl Fn ( & ( K , V ) ) -> bool + ' _ {
33
+ move |x| x. 0 == * k
34
+ }
35
+
32
36
pub struct QueryState < K > {
33
- active : Sharded < FxHashMap < K , QueryResult > > ,
37
+ active : Sharded < hashbrown :: HashTable < ( K , QueryResult ) > > ,
34
38
}
35
39
36
40
/// Indicates the state of a query for a given key in a query map.
@@ -163,7 +167,7 @@ where
163
167
{
164
168
/// Completes the query by updating the query cache with the `result`,
165
169
/// 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 )
167
171
where
168
172
C : QueryCache < Key = K > ,
169
173
{
@@ -178,16 +182,17 @@ where
178
182
cache. complete ( key, result, dep_node_index) ;
179
183
180
184
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
+ }
190
194
} ;
195
+ let job = job. expect ( "active query job entry" ) . expect_job ( ) ;
191
196
192
197
job. signal_complete ( ) ;
193
198
}
@@ -203,11 +208,16 @@ where
203
208
// Poison the query so jobs waiting on it panic.
204
209
let state = self . state ;
205
210
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
+ }
211
221
} ;
212
222
// Also signal the completion of the job, so waiters
213
223
// will continue execution.
@@ -287,11 +297,11 @@ where
287
297
outline ( || {
288
298
// We didn't find the query result in the query cache. Check if it was
289
299
// 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) ) {
293
303
// The query we waited on panicked. Continue unwinding here.
294
- Some ( QueryResult :: Poisoned ) => FatalError . raise ( ) ,
304
+ Some ( ( _ , QueryResult :: Poisoned ) ) => FatalError . raise ( ) ,
295
305
_ => panic ! (
296
306
"query '{}' result must be in the cache or the query must be poisoned after a wait" ,
297
307
query. name( )
@@ -322,7 +332,8 @@ where
322
332
Qcx : QueryContext ,
323
333
{
324
334
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) ;
326
337
327
338
// For the parallel compiler we need to check both the query cache and query state structures
328
339
// while holding the state lock to ensure that 1) the query has not yet completed and 2) the
@@ -339,21 +350,21 @@ where
339
350
340
351
let current_job_id = qcx. current_query_job ( ) ;
341
352
342
- match state_lock. entry ( key) {
353
+ match state_lock. entry ( key_hash , equivalent_key ( & key) , | ( k , _ ) | sharded :: make_hash ( k ) ) {
343
354
Entry :: Vacant ( entry) => {
344
355
// Nothing has computed or is computing the query, so we start a new job and insert it in the
345
356
// state map.
346
357
let id = qcx. next_job_id ( ) ;
347
358
let job = QueryJob :: new ( id, span, current_job_id) ;
348
- entry. insert ( QueryResult :: Started ( job) ) ;
359
+ entry. insert ( ( key , QueryResult :: Started ( job) ) ) ;
349
360
350
361
// Drop the lock before we start executing the query
351
362
drop ( state_lock) ;
352
363
353
- execute_job :: < _ , _ , INCR > ( query, qcx, state, key, id, dep_node)
364
+ execute_job :: < _ , _ , INCR > ( query, qcx, state, key, key_hash , id, dep_node)
354
365
}
355
366
Entry :: Occupied ( mut entry) => {
356
- match entry. get_mut ( ) {
367
+ match & mut entry. get_mut ( ) . 1 {
357
368
QueryResult :: Started ( job) => {
358
369
if sync:: is_dyn_thread_safe ( ) {
359
370
// Get the latch out
@@ -384,6 +395,7 @@ fn execute_job<Q, Qcx, const INCR: bool>(
384
395
qcx : Qcx ,
385
396
state : & QueryState < Q :: Key > ,
386
397
key : Q :: Key ,
398
+ key_hash : u64 ,
387
399
id : QueryJobId ,
388
400
dep_node : Option < DepNode > ,
389
401
) -> ( Q :: Value , Option < DepNodeIndex > )
@@ -444,7 +456,7 @@ where
444
456
}
445
457
}
446
458
}
447
- job_owner. complete ( cache, result, dep_node_index) ;
459
+ job_owner. complete ( cache, key_hash , result, dep_node_index) ;
448
460
449
461
( result, Some ( dep_node_index) )
450
462
}
0 commit comments