@@ -12,12 +12,12 @@ use crate::query::{QueryContext, QueryMap, QuerySideEffects, QueryStackFrame};
12
12
13
13
use rustc_data_structures:: fingerprint:: Fingerprint ;
14
14
use rustc_data_structures:: fx:: { FxHashMap , FxHasher } ;
15
+ #[ cfg( parallel_compiler) ]
16
+ use rustc_data_structures:: profiling:: TimingGuard ;
15
17
use rustc_data_structures:: sharded:: { get_shard_index_by_hash, Sharded } ;
16
18
use rustc_data_structures:: sync:: { Lock , LockGuard } ;
17
19
use rustc_data_structures:: thin_vec:: ThinVec ;
18
- #[ cfg( not( parallel_compiler) ) ]
19
- use rustc_errors:: DiagnosticBuilder ;
20
- use rustc_errors:: { Diagnostic , FatalError } ;
20
+ use rustc_errors:: { Diagnostic , DiagnosticBuilder , FatalError } ;
21
21
use rustc_span:: { Span , DUMMY_SP } ;
22
22
use std:: cell:: Cell ;
23
23
use std:: collections:: hash_map:: Entry ;
@@ -147,24 +147,21 @@ impl<D, K> Default for QueryState<D, K> {
147
147
148
148
/// A type representing the responsibility to execute the job in the `job` field.
149
149
/// This will poison the relevant query if dropped.
150
- struct JobOwner < ' tcx , D , C >
150
+ struct JobOwner < ' tcx , D , K >
151
151
where
152
152
D : Copy + Clone + Eq + Hash ,
153
- C : QueryCache ,
153
+ K : Eq + Hash + Clone ,
154
154
{
155
- state : & ' tcx QueryState < D , C :: Key > ,
156
- cache : & ' tcx QueryCacheStore < C > ,
157
- key : C :: Key ,
155
+ state : & ' tcx QueryState < D , K > ,
156
+ key : K ,
158
157
id : QueryJobId < D > ,
159
158
}
160
159
161
160
#[ cold]
162
161
#[ inline( never) ]
163
- #[ cfg( not( parallel_compiler) ) ]
164
162
fn mk_cycle < CTX , V , R > (
165
163
tcx : CTX ,
166
- root : QueryJobId < CTX :: DepKind > ,
167
- span : Span ,
164
+ error : CycleError ,
168
165
handle_cycle_error : fn ( CTX , DiagnosticBuilder < ' _ > ) -> V ,
169
166
cache : & dyn crate :: query:: QueryStorage < Value = V , Stored = R > ,
170
167
) -> R
@@ -173,20 +170,15 @@ where
173
170
V : std:: fmt:: Debug ,
174
171
R : Clone ,
175
172
{
176
- let error: CycleError = root. find_cycle_in_stack (
177
- tcx. try_collect_active_jobs ( ) . unwrap ( ) ,
178
- & tcx. current_query_job ( ) ,
179
- span,
180
- ) ;
181
173
let error = report_cycle ( tcx. dep_context ( ) . sess ( ) , error) ;
182
174
let value = handle_cycle_error ( tcx, error) ;
183
175
cache. store_nocache ( value)
184
176
}
185
177
186
- impl < ' tcx , D , C > JobOwner < ' tcx , D , C >
178
+ impl < ' tcx , D , K > JobOwner < ' tcx , D , K >
187
179
where
188
180
D : Copy + Clone + Eq + Hash ,
189
- C : QueryCache ,
181
+ K : Eq + Hash + Clone ,
190
182
{
191
183
/// Either gets a `JobOwner` corresponding the query, allowing us to
192
184
/// start executing the query, or returns with the result of the query.
@@ -198,14 +190,13 @@ where
198
190
/// for some compile-time benchmarks.
199
191
#[ inline( always) ]
200
192
fn try_start < ' b , CTX > (
201
- tcx : CTX ,
202
- state : & ' b QueryState < CTX :: DepKind , C :: Key > ,
203
- cache : & ' b QueryCacheStore < C > ,
193
+ tcx : & ' b CTX ,
194
+ state : & ' b QueryState < CTX :: DepKind , K > ,
204
195
span : Span ,
205
- key : C :: Key ,
196
+ key : K ,
206
197
lookup : QueryLookup ,
207
- query : & QueryVtable < CTX , C :: Key , C :: Value > ,
208
- ) -> TryGetJob < ' b , CTX :: DepKind , C >
198
+ dep_kind : CTX :: DepKind ,
199
+ ) -> TryGetJob < ' b , CTX :: DepKind , K >
209
200
where
210
201
CTX : QueryContext ,
211
202
{
@@ -226,26 +217,24 @@ where
226
217
let key = entry. key ( ) . clone ( ) ;
227
218
entry. insert ( QueryResult :: Started ( job) ) ;
228
219
229
- let global_id = QueryJobId :: new ( id, shard, query . dep_kind ) ;
230
- let owner = JobOwner { state, cache , id : global_id, key } ;
220
+ let global_id = QueryJobId :: new ( id, shard, dep_kind) ;
221
+ let owner = JobOwner { state, id : global_id, key } ;
231
222
return TryGetJob :: NotYetStarted ( owner) ;
232
223
}
233
224
Entry :: Occupied ( mut entry) => {
234
225
match entry. get_mut ( ) {
235
226
#[ cfg( not( parallel_compiler) ) ]
236
227
QueryResult :: Started ( job) => {
237
- let id = QueryJobId :: new ( job. id , shard, query . dep_kind ) ;
228
+ let id = QueryJobId :: new ( job. id , shard, dep_kind) ;
238
229
239
230
drop ( state_lock) ;
240
231
241
232
// If we are single-threaded we know that we have cycle error,
242
233
// so we just return the error.
243
- return TryGetJob :: Cycle ( mk_cycle (
244
- tcx,
245
- id ,
234
+ return TryGetJob :: Cycle ( id . find_cycle_in_stack (
235
+ tcx. try_collect_active_jobs ( ) . unwrap ( ) ,
236
+ & tcx . current_query_job ( ) ,
246
237
span,
247
- query. handle_cycle_error ,
248
- & cache. cache ,
249
238
) ) ;
250
239
}
251
240
#[ cfg( parallel_compiler) ]
@@ -257,38 +246,17 @@ where
257
246
258
247
// Get the latch out
259
248
let latch = job. latch ( ) ;
260
- let key = entry. key ( ) . clone ( ) ;
261
249
262
250
drop ( state_lock) ;
263
251
264
252
// With parallel queries we might just have to wait on some other
265
253
// thread.
266
254
let result = latch. wait_on ( tcx. current_query_job ( ) , span) ;
267
255
268
- if let Err ( cycle) = result {
269
- let cycle = report_cycle ( tcx. dep_context ( ) . sess ( ) , cycle) ;
270
- let value = ( query. handle_cycle_error ) ( tcx, cycle) ;
271
- let value = cache. cache . store_nocache ( value) ;
272
- return TryGetJob :: Cycle ( value) ;
256
+ match result {
257
+ Ok ( ( ) ) => TryGetJob :: JobCompleted ( query_blocked_prof_timer) ,
258
+ Err ( cycle) => TryGetJob :: Cycle ( cycle) ,
273
259
}
274
-
275
- let cached = cache
276
- . cache
277
- . lookup ( cache, & key, |value, index| {
278
- if unlikely ! ( tcx. dep_context( ) . profiler( ) . enabled( ) ) {
279
- tcx. dep_context ( ) . profiler ( ) . query_cache_hit ( index. into ( ) ) ;
280
- }
281
- #[ cfg( debug_assertions) ]
282
- {
283
- cache. cache_hits . fetch_add ( 1 , Ordering :: Relaxed ) ;
284
- }
285
- ( value. clone ( ) , index)
286
- } )
287
- . unwrap_or_else ( |_| panic ! ( "value must be in cache after waiting" ) ) ;
288
-
289
- query_blocked_prof_timer. finish_with_query_invocation_id ( cached. 1 . into ( ) ) ;
290
-
291
- return TryGetJob :: JobCompleted ( cached) ;
292
260
}
293
261
QueryResult :: Poisoned => FatalError . raise ( ) ,
294
262
}
@@ -298,11 +266,18 @@ where
298
266
299
267
/// Completes the query by updating the query cache with the `result`,
300
268
/// signals the waiter and forgets the JobOwner, so it won't poison the query
301
- fn complete ( self , result : C :: Value , dep_node_index : DepNodeIndex ) -> C :: Stored {
269
+ fn complete < C > (
270
+ self ,
271
+ cache : & QueryCacheStore < C > ,
272
+ result : C :: Value ,
273
+ dep_node_index : DepNodeIndex ,
274
+ ) -> C :: Stored
275
+ where
276
+ C : QueryCache < Key = K > ,
277
+ {
302
278
// We can move out of `self` here because we `mem::forget` it below
303
279
let key = unsafe { ptr:: read ( & self . key ) } ;
304
280
let state = self . state ;
305
- let cache = self . cache ;
306
281
307
282
// Forget ourself so our destructor won't poison the query
308
283
mem:: forget ( self ) ;
@@ -338,10 +313,10 @@ where
338
313
( result, diagnostics. into_inner ( ) )
339
314
}
340
315
341
- impl < ' tcx , D , C > Drop for JobOwner < ' tcx , D , C >
316
+ impl < ' tcx , D , K > Drop for JobOwner < ' tcx , D , K >
342
317
where
343
318
D : Copy + Clone + Eq + Hash ,
344
- C : QueryCache ,
319
+ K : Eq + Hash + Clone ,
345
320
{
346
321
#[ inline( never) ]
347
322
#[ cold]
@@ -372,22 +347,22 @@ pub(crate) struct CycleError {
372
347
}
373
348
374
349
/// The result of `try_start`.
375
- enum TryGetJob < ' tcx , D , C >
350
+ enum TryGetJob < ' tcx , D , K >
376
351
where
377
352
D : Copy + Clone + Eq + Hash ,
378
- C : QueryCache ,
353
+ K : Eq + Hash + Clone ,
379
354
{
380
355
/// The query is not yet started. Contains a guard to the cache eventually used to start it.
381
- NotYetStarted ( JobOwner < ' tcx , D , C > ) ,
356
+ NotYetStarted ( JobOwner < ' tcx , D , K > ) ,
382
357
383
358
/// The query was already completed.
384
359
/// Returns the result of the query and its dep-node index
385
360
/// if it succeeded or a cycle error if it failed.
386
361
#[ cfg( parallel_compiler) ]
387
- JobCompleted ( ( C :: Stored , DepNodeIndex ) ) ,
362
+ JobCompleted ( TimingGuard < ' tcx > ) ,
388
363
389
364
/// Trying to execute the query resulted in a cycle.
390
- Cycle ( C :: Stored ) ,
365
+ Cycle ( CycleError ) ,
391
366
}
392
367
393
368
/// Checks if the query is already computed and in the cache.
@@ -436,19 +411,35 @@ where
436
411
C :: Key : Clone + DepNodeParams < CTX :: DepContext > ,
437
412
CTX : QueryContext ,
438
413
{
439
- let job = match JobOwner :: < ' _ , CTX :: DepKind , C > :: try_start (
440
- tcx,
414
+ let job = match JobOwner :: < ' _ , CTX :: DepKind , C :: Key > :: try_start (
415
+ & tcx,
441
416
state,
442
- cache,
443
417
span,
444
418
key. clone ( ) ,
445
419
lookup,
446
- query,
420
+ query. dep_kind ,
447
421
) {
448
422
TryGetJob :: NotYetStarted ( job) => job,
449
- TryGetJob :: Cycle ( result) => return ( result, None ) ,
423
+ TryGetJob :: Cycle ( error) => {
424
+ let result = mk_cycle ( tcx, error, query. handle_cycle_error , & cache. cache ) ;
425
+ return ( result, None ) ;
426
+ }
450
427
#[ cfg( parallel_compiler) ]
451
- TryGetJob :: JobCompleted ( ( v, index) ) => {
428
+ TryGetJob :: JobCompleted ( query_blocked_prof_timer) => {
429
+ let ( v, index) = cache
430
+ . cache
431
+ . lookup ( cache, & key, |value, index| ( value. clone ( ) , index) )
432
+ . unwrap_or_else ( |_| panic ! ( "value must be in cache after waiting" ) ) ;
433
+
434
+ if unlikely ! ( tcx. dep_context( ) . profiler( ) . enabled( ) ) {
435
+ tcx. dep_context ( ) . profiler ( ) . query_cache_hit ( index. into ( ) ) ;
436
+ }
437
+ #[ cfg( debug_assertions) ]
438
+ {
439
+ cache. cache_hits . fetch_add ( 1 , Ordering :: Relaxed ) ;
440
+ }
441
+ query_blocked_prof_timer. finish_with_query_invocation_id ( index. into ( ) ) ;
442
+
452
443
return ( v, Some ( index) ) ;
453
444
}
454
445
} ;
@@ -461,7 +452,7 @@ where
461
452
let result = tcx. start_query ( job. id , None , || compute ( * tcx. dep_context ( ) , key) ) ;
462
453
let dep_node_index = dep_graph. next_virtual_depnode_index ( ) ;
463
454
prof_timer. finish_with_query_invocation_id ( dep_node_index. into ( ) ) ;
464
- let result = job. complete ( result, dep_node_index) ;
455
+ let result = job. complete ( cache , result, dep_node_index) ;
465
456
return ( result, None ) ;
466
457
}
467
458
@@ -504,7 +495,7 @@ where
504
495
force_query_with_job ( tcx, key, job. id , dep_node, query, compute)
505
496
}
506
497
} ;
507
- let result = job. complete ( result, dep_node_index) ;
498
+ let result = job. complete ( cache , result, dep_node_index) ;
508
499
( result, Some ( dep_node_index) )
509
500
}
510
501
0 commit comments