@@ -12,26 +12,27 @@ 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_map:: RawEntryMut ;
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:: { cold_path, sync} ;
2222use rustc_errors:: { DiagnosticBuilder , ErrorGuaranteed , FatalError } ;
23+ use rustc_hash:: FxHasher ;
2324use rustc_span:: { Span , DUMMY_SP } ;
2425use std:: cell:: Cell ;
25- use std:: collections:: hash_map:: Entry ;
2626use std:: fmt:: Debug ;
27+ use std:: hash:: BuildHasherDefault ;
2728use std:: hash:: Hash ;
2829use std:: mem;
2930use thin_vec:: ThinVec ;
3031
3132use super :: QueryConfig ;
3233
3334pub struct QueryState < K , D : DepKind > {
34- active : Sharded < FxHashMap < K , QueryResult < D > > > ,
35+ active : Sharded < hashbrown :: HashMap < K , QueryResult < D > , BuildHasherDefault < FxHasher > > > ,
3536}
3637
3738/// Indicates the state of a query for a given key in a query map.
@@ -143,7 +144,7 @@ where
143144{
144145 /// Completes the query by updating the query cache with the `result`,
145146 /// signals the waiter and forgets the JobOwner, so it won't poison the query
146- fn complete < C > ( self , cache : & C , result : C :: Value , dep_node_index : DepNodeIndex )
147+ fn complete < C > ( self , cache : & C , key_hash : u64 , result : C :: Value , dep_node_index : DepNodeIndex )
147148 where
148149 C : QueryCache < Key = K > ,
149150 {
@@ -155,13 +156,17 @@ where
155156
156157 // Mark as complete before we remove the job from the active state
157158 // so no other thread can re-execute this query.
158- cache. complete ( key, result, dep_node_index) ;
159+ cache. complete ( key, key_hash , result, dep_node_index) ;
159160
160161 let job = {
161- let mut lock = state. active . lock_shard_by_value ( & key) ;
162- match lock. remove ( & key) . unwrap ( ) {
163- QueryResult :: Started ( job) => job,
164- QueryResult :: Poisoned => panic ! ( ) ,
162+ let mut lock = state. active . lock_shard_by_hash ( key_hash) ;
163+
164+ match lock. raw_entry_mut ( ) . from_key_hashed_nocheck ( key_hash, & key) {
165+ RawEntryMut :: Vacant ( _) => panic ! ( ) ,
166+ RawEntryMut :: Occupied ( occupied) => match occupied. remove ( ) {
167+ QueryResult :: Started ( job) => job,
168+ QueryResult :: Poisoned => panic ! ( ) ,
169+ } ,
165170 }
166171 } ;
167172
@@ -211,7 +216,8 @@ where
211216 C : QueryCache ,
212217 Tcx : DepContext ,
213218{
214- match cache. lookup ( & key) {
219+ let key_hash = sharded:: make_hash ( key) ;
220+ match cache. lookup ( & key, key_hash) {
215221 Some ( ( value, index) ) => {
216222 tcx. profiler ( ) . query_cache_hit ( index. into ( ) ) ;
217223 tcx. dep_graph ( ) . read_index ( index) ;
@@ -248,6 +254,7 @@ fn wait_for_query<Q, Qcx>(
248254 qcx : Qcx ,
249255 span : Span ,
250256 key : Q :: Key ,
257+ key_hash : u64 ,
251258 latch : QueryLatch < Qcx :: DepKind > ,
252259 current : Option < QueryJobId > ,
253260) -> ( Q :: Value , Option < DepNodeIndex > )
@@ -266,7 +273,7 @@ where
266273
267274 match result {
268275 Ok ( ( ) ) => {
269- let Some ( ( v, index) ) = query. query_cache ( qcx) . lookup ( & key) else {
276+ let Some ( ( v, index) ) = query. query_cache ( qcx) . lookup ( & key, key_hash ) else {
270277 cold_path ( || {
271278 // We didn't find the query result in the query cache. Check if it was
272279 // poisoned due to a panic instead.
@@ -303,7 +310,8 @@ where
303310 Qcx : QueryContext ,
304311{
305312 let state = query. query_state ( qcx) ;
306- let mut state_lock = state. active . lock_shard_by_value ( & key) ;
313+ let key_hash = sharded:: make_hash ( & key) ;
314+ let mut state_lock = state. active . lock_shard_by_hash ( key_hash) ;
307315
308316 // For the parallel compiler we need to check both the query cache and query state structures
309317 // while holding the state lock to ensure that 1) the query has not yet completed and 2) the
@@ -312,28 +320,28 @@ where
312320 // executing, but another thread may have already completed the query and stores it result
313321 // in the query cache.
314322 if cfg ! ( parallel_compiler) && qcx. dep_context ( ) . sess ( ) . threads ( ) > 1 {
315- if let Some ( ( value, index) ) = query. query_cache ( qcx) . lookup ( & key) {
323+ if let Some ( ( value, index) ) = query. query_cache ( qcx) . lookup ( & key, key_hash ) {
316324 qcx. dep_context ( ) . profiler ( ) . query_cache_hit ( index. into ( ) ) ;
317325 return ( value, Some ( index) ) ;
318326 }
319327 }
320328
321329 let current_job_id = qcx. current_query_job ( ) ;
322330
323- match state_lock. entry ( key) {
324- Entry :: Vacant ( entry) => {
331+ match state_lock. raw_entry_mut ( ) . from_key_hashed_nocheck ( key_hash , & key) {
332+ RawEntryMut :: Vacant ( entry) => {
325333 // Nothing has computed or is computing the query, so we start a new job and insert it in the
326334 // state map.
327335 let id = qcx. next_job_id ( ) ;
328336 let job = QueryJob :: new ( id, span, current_job_id) ;
329- entry. insert ( QueryResult :: Started ( job) ) ;
337+ entry. insert_hashed_nocheck ( key_hash , key , QueryResult :: Started ( job) ) ;
330338
331339 // Drop the lock before we start executing the query
332340 drop ( state_lock) ;
333341
334- execute_job :: < _ , _ , INCR > ( query, qcx, state, key, id, dep_node)
342+ execute_job :: < _ , _ , INCR > ( query, qcx, state, key, key_hash , id, dep_node)
335343 }
336- Entry :: Occupied ( mut entry) => {
344+ RawEntryMut :: Occupied ( mut entry) => {
337345 match entry. get_mut ( ) {
338346 QueryResult :: Started ( job) => {
339347 #[ cfg( parallel_compiler) ]
@@ -344,7 +352,15 @@ where
344352
345353 // Only call `wait_for_query` if we're using a Rayon thread pool
346354 // as it will attempt to mark the worker thread as blocked.
347- return wait_for_query ( query, qcx, span, key, latch, current_job_id) ;
355+ return wait_for_query (
356+ query,
357+ qcx,
358+ span,
359+ key,
360+ key_hash,
361+ latch,
362+ current_job_id,
363+ ) ;
348364 }
349365
350366 let id = job. id ;
@@ -366,6 +382,7 @@ fn execute_job<Q, Qcx, const INCR: bool>(
366382 qcx : Qcx ,
367383 state : & QueryState < Q :: Key , Qcx :: DepKind > ,
368384 key : Q :: Key ,
385+ key_hash : u64 ,
369386 id : QueryJobId ,
370387 dep_node : Option < DepNode < Qcx :: DepKind > > ,
371388) -> ( Q :: Value , Option < DepNodeIndex > )
@@ -397,7 +414,7 @@ where
397414 // This can't happen, as query feeding adds the very dependencies to the fed query
398415 // as its feeding query had. So if the fed query is red, so is its feeder, which will
399416 // get evaluated first, and re-feed the query.
400- if let Some ( ( cached_result, _) ) = cache. lookup ( & key) {
417+ if let Some ( ( cached_result, _) ) = cache. lookup ( & key, key_hash ) {
401418 let Some ( hasher) = query. hash_result ( ) else {
402419 panic ! (
403420 "no_hash fed query later has its value computed.\n \
@@ -429,7 +446,7 @@ where
429446 }
430447 }
431448 }
432- job_owner. complete ( cache, result, dep_node_index) ;
449+ job_owner. complete ( cache, key_hash , result, dep_node_index) ;
433450
434451 ( result, Some ( dep_node_index) )
435452}
@@ -832,7 +849,7 @@ pub fn force_query<Q, Qcx>(
832849{
833850 // We may be concurrently trying both execute and force a query.
834851 // Ensure that only one of them runs the query.
835- if let Some ( ( _, index) ) = query. query_cache ( qcx) . lookup ( & key) {
852+ if let Some ( ( _, index) ) = query. query_cache ( qcx) . lookup ( & key, sharded :: make_hash ( & key ) ) {
836853 qcx. dep_context ( ) . profiler ( ) . query_cache_hit ( index. into ( ) ) ;
837854 return ;
838855 }
0 commit comments