1
- use parking_lot:: Mutex ;
2
1
use rustc_data_structures:: fingerprint:: Fingerprint ;
3
2
use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
4
3
use rustc_data_structures:: profiling:: { EventId , QueryInvocationId , SelfProfilerRef } ;
5
4
use rustc_data_structures:: sharded:: { self , Sharded } ;
6
5
use rustc_data_structures:: stable_hasher:: { HashStable , StableHasher } ;
7
6
use rustc_data_structures:: steal:: Steal ;
8
7
use rustc_data_structures:: sync:: { AtomicU32 , AtomicU64 , Lock , Lrc , Ordering } ;
8
+ use rustc_data_structures:: thin_vec:: ThinVec ;
9
+ use rustc_data_structures:: unlikely;
10
+ use rustc_errors:: Diagnostic ;
9
11
use rustc_index:: vec:: IndexVec ;
10
12
use rustc_serialize:: opaque:: { FileEncodeResult , FileEncoder } ;
13
+
14
+ use parking_lot:: Mutex ;
11
15
use smallvec:: { smallvec, SmallVec } ;
12
16
use std:: collections:: hash_map:: Entry ;
13
17
use std:: fmt:: Debug ;
@@ -19,7 +23,7 @@ use super::query::DepGraphQuery;
19
23
use super :: serialized:: { GraphEncoder , SerializedDepGraph , SerializedDepNodeIndex } ;
20
24
use super :: { DepContext , DepKind , DepNode , HasDepContext , WorkProductId } ;
21
25
use crate :: ich:: StableHashingContext ;
22
- use crate :: query:: { QueryContext , QuerySideEffects } ;
26
+ use crate :: query:: { QueryContext , QueryJobId , QuerySideEffects } ;
23
27
24
28
#[ cfg( debug_assertions) ]
25
29
use { super :: debug:: EdgeFilter , std:: env} ;
@@ -151,7 +155,7 @@ impl DepGraph {
151
155
self . data . is_some ( )
152
156
}
153
157
154
- pub fn with_query ( & self , f : impl Fn ( & DepGraphQuery ) ) {
158
+ pub fn with_debug ( & self , f : impl Fn ( & DepGraphQuery ) ) {
155
159
if let Some ( data) = & self . data {
156
160
data. current . encoder . borrow ( ) . with_query ( f)
157
161
}
@@ -209,7 +213,13 @@ impl DepGraph {
209
213
hash_result : Option < fn ( & mut StableHashingContext < ' _ > , & R ) -> Fingerprint > ,
210
214
) -> ( R , DepNodeIndex ) {
211
215
if self . is_fully_enabled ( ) {
212
- self . with_task_impl ( key, cx, arg, task, hash_result)
216
+ self . with_task_impl (
217
+ key,
218
+ cx,
219
+ arg,
220
+ |arg, task_deps| crate :: tls:: with_deps ( task_deps, || task ( cx, arg) ) ,
221
+ hash_result,
222
+ )
213
223
} else {
214
224
// Incremental compilation is turned off. We just execute the task
215
225
// without tracking. We still provide a dep-node index that uniquely
@@ -219,12 +229,35 @@ impl DepGraph {
219
229
}
220
230
}
221
231
232
+ pub ( crate ) fn with_query < Ctxt : QueryContext , A : Debug , R > (
233
+ & self ,
234
+ key : DepNode ,
235
+ cx : Ctxt ,
236
+ arg : A ,
237
+ token : QueryJobId ,
238
+ diagnostics : Option < & Lock < ThinVec < Diagnostic > > > ,
239
+ task : fn ( Ctxt :: DepContext , A ) -> R ,
240
+ hash_result : Option < fn ( & mut StableHashingContext < ' _ > , & R ) -> Fingerprint > ,
241
+ ) -> ( R , DepNodeIndex ) {
242
+ self . with_task_impl (
243
+ key,
244
+ cx,
245
+ arg,
246
+ |arg, task_deps| {
247
+ crate :: tls:: start_query ( token, diagnostics, task_deps, || {
248
+ task ( * cx. dep_context ( ) , arg)
249
+ } )
250
+ } ,
251
+ hash_result,
252
+ )
253
+ }
254
+
222
255
fn with_task_impl < Ctxt : HasDepContext , A : Debug , R > (
223
256
& self ,
224
257
key : DepNode ,
225
258
cx : Ctxt ,
226
259
arg : A ,
227
- task : fn ( Ctxt , A ) -> R ,
260
+ invoke : impl FnOnce ( A , Option < & Lock < TaskDeps > > ) -> R ,
228
261
hash_result : Option < fn ( & mut StableHashingContext < ' _ > , & R ) -> Fingerprint > ,
229
262
) -> ( R , DepNodeIndex ) {
230
263
// This function is only called when the graph is enabled.
@@ -255,7 +288,7 @@ impl DepGraph {
255
288
phantom_data : PhantomData ,
256
289
} ) )
257
290
} ;
258
- let result = crate :: tls :: with_deps ( task_deps. as_ref ( ) , || task ( cx , arg ) ) ;
291
+ let result = invoke ( arg , task_deps. as_ref ( ) ) ;
259
292
let edges = task_deps. map_or_else ( || smallvec ! [ ] , |lock| lock. into_inner ( ) . reads ) ;
260
293
261
294
let dcx = cx. dep_context ( ) ;
@@ -306,57 +339,88 @@ impl DepGraph {
306
339
{
307
340
debug_assert ! ( !cx. is_eval_always( dep_kind) ) ;
308
341
309
- if let Some ( ref data) = self . data {
310
- let task_deps = Lock :: new ( TaskDeps :: default ( ) ) ;
311
- let result = crate :: tls:: with_deps ( Some ( & task_deps) , op) ;
312
- let task_deps = task_deps. into_inner ( ) ;
313
- let task_deps = task_deps. reads ;
314
-
315
- let dep_node_index = match task_deps. len ( ) {
316
- 0 => {
317
- // Because the dep-node id of anon nodes is computed from the sets of its
318
- // dependencies we already know what the ID of this dependency-less node is
319
- // going to be (i.e. equal to the precomputed
320
- // `SINGLETON_DEPENDENCYLESS_ANON_NODE`). As a consequence we can skip creating
321
- // a `StableHasher` and sending the node through interning.
322
- DepNodeIndex :: SINGLETON_DEPENDENCYLESS_ANON_NODE
323
- }
324
- 1 => {
325
- // When there is only one dependency, don't bother creating a node.
326
- task_deps[ 0 ]
327
- }
328
- _ => {
329
- // The dep node indices are hashed here instead of hashing the dep nodes of the
330
- // dependencies. These indices may refer to different nodes per session, but this isn't
331
- // a problem here because we that ensure the final dep node hash is per session only by
332
- // combining it with the per session random number `anon_id_seed`. This hash only need
333
- // to map the dependencies to a single value on a per session basis.
334
- let mut hasher = StableHasher :: new ( ) ;
335
- task_deps. hash ( & mut hasher) ;
336
-
337
- let target_dep_node = DepNode {
338
- kind : dep_kind,
339
- // Fingerprint::combine() is faster than sending Fingerprint
340
- // through the StableHasher (at least as long as StableHasher
341
- // is so slow).
342
- hash : data. current . anon_id_seed . combine ( hasher. finish ( ) ) . into ( ) ,
343
- } ;
344
-
345
- data. current . intern_new_node (
346
- cx. profiler ( ) ,
347
- target_dep_node,
348
- task_deps,
349
- Fingerprint :: ZERO ,
350
- )
351
- }
352
- } ;
353
-
354
- ( result, dep_node_index)
342
+ if self . is_fully_enabled ( ) {
343
+ self . with_anon_task_impl ( * cx. dep_context ( ) , dep_kind, |task_deps| {
344
+ crate :: tls:: with_deps ( task_deps, op)
345
+ } )
355
346
} else {
356
347
( op ( ) , self . next_virtual_depnode_index ( ) )
357
348
}
358
349
}
359
350
351
+ /// Executes something within an "anonymous" task, that is, a task the
352
+ /// `DepNode` of which is determined by the list of inputs it read from.
353
+ pub ( crate ) fn with_anon_query < Ctxt : QueryContext , A , R > (
354
+ & self ,
355
+ dep_kind : DepKind ,
356
+ cx : Ctxt ,
357
+ arg : A ,
358
+ token : QueryJobId ,
359
+ diagnostics : Option < & Lock < ThinVec < Diagnostic > > > ,
360
+ task : fn ( Ctxt :: DepContext , A ) -> R ,
361
+ ) -> ( R , DepNodeIndex ) {
362
+ debug_assert ! ( !cx. dep_context( ) . is_eval_always( dep_kind) ) ;
363
+
364
+ self . with_anon_task_impl ( * cx. dep_context ( ) , dep_kind, |task_deps| {
365
+ crate :: tls:: start_query ( token, diagnostics, task_deps, || task ( * cx. dep_context ( ) , arg) )
366
+ } )
367
+ }
368
+
369
+ fn with_anon_task_impl < Ctxt : DepContext , R > (
370
+ & self ,
371
+ cx : Ctxt ,
372
+ dep_kind : DepKind ,
373
+ invoke : impl FnOnce ( Option < & Lock < TaskDeps > > ) -> R ,
374
+ ) -> ( R , DepNodeIndex ) {
375
+ debug_assert ! ( !cx. dep_context( ) . is_eval_always( dep_kind) ) ;
376
+
377
+ let data = self . data . as_ref ( ) . unwrap ( ) ;
378
+ let task_deps = Lock :: new ( TaskDeps :: default ( ) ) ;
379
+ let result = invoke ( Some ( & task_deps) ) ;
380
+ let task_deps = task_deps. into_inner ( ) . reads ;
381
+
382
+ let dep_node_index = match task_deps. len ( ) {
383
+ 0 => {
384
+ // Because the dep-node id of anon nodes is computed from the sets of its
385
+ // dependencies we already know what the ID of this dependency-less node is
386
+ // going to be (i.e. equal to the precomputed
387
+ // `SINGLETON_DEPENDENCYLESS_ANON_NODE`). As a consequence we can skip creating
388
+ // a `StableHasher` and sending the node through interning.
389
+ DepNodeIndex :: SINGLETON_DEPENDENCYLESS_ANON_NODE
390
+ }
391
+ 1 => {
392
+ // When there is only one dependency, don't bother creating a node.
393
+ task_deps[ 0 ]
394
+ }
395
+ _ => {
396
+ // The dep node indices are hashed here instead of hashing the dep nodes of the
397
+ // dependencies. These indices may refer to different nodes per session, but this isn't
398
+ // a problem here because we that ensure the final dep node hash is per session only by
399
+ // combining it with the per session random number `anon_id_seed`. This hash only need
400
+ // to map the dependencies to a single value on a per session basis.
401
+ let mut hasher = StableHasher :: new ( ) ;
402
+ task_deps. hash ( & mut hasher) ;
403
+
404
+ let target_dep_node = DepNode {
405
+ kind : dep_kind,
406
+ // Fingerprint::combine() is faster than sending Fingerprint
407
+ // through the StableHasher (at least as long as StableHasher
408
+ // is so slow).
409
+ hash : data. current . anon_id_seed . combine ( hasher. finish ( ) ) . into ( ) ,
410
+ } ;
411
+
412
+ data. current . intern_new_node (
413
+ cx. profiler ( ) ,
414
+ target_dep_node,
415
+ task_deps,
416
+ Fingerprint :: ZERO ,
417
+ )
418
+ }
419
+ } ;
420
+
421
+ ( result, dep_node_index)
422
+ }
423
+
360
424
#[ inline]
361
425
pub fn read_index ( & self , dep_node_index : DepNodeIndex ) {
362
426
if let Some ( ref data) = self . data {
0 commit comments