@@ -17,9 +17,9 @@ use rustc::ich::Fingerprint;
17
17
use rustc:: session:: Session ;
18
18
use rustc:: ty:: TyCtxt ;
19
19
use rustc_data_structures:: fx:: { FxHashSet , FxHashMap } ;
20
+ use rustc_data_structures:: indexed_vec:: IndexVec ;
20
21
use rustc_serialize:: Decodable as RustcDecodable ;
21
22
use rustc_serialize:: opaque:: Decoder ;
22
- use std:: default:: Default ;
23
23
use std:: path:: { Path } ;
24
24
25
25
use IncrementalHashesMap ;
@@ -32,7 +32,7 @@ use super::work_product;
32
32
33
33
// The key is a dirty node. The value is **some** base-input that we
34
34
// can blame it on.
35
- pub type DirtyNodes = FxHashMap < DepNode , DepNode > ;
35
+ pub type DirtyNodes = FxHashMap < DepNodeIndex , DepNodeIndex > ;
36
36
37
37
/// If we are in incremental mode, and a previous dep-graph exists,
38
38
/// then load up those nodes/edges that are still valid into the
@@ -166,48 +166,35 @@ pub fn decode_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
166
166
167
167
let serialized_dep_graph = SerializedDepGraph :: decode ( & mut dep_graph_decoder) ?;
168
168
169
- let edge_map: FxHashMap < DepNode , Vec < DepNode > > = {
170
- let capacity = serialized_dep_graph. edge_list_data . len ( ) ;
171
- let mut edge_map = FxHashMap :: with_capacity_and_hasher ( capacity, Default :: default ( ) ) ;
172
-
173
- for ( node_index, source) in serialized_dep_graph. nodes . iter ( ) . enumerate ( ) {
174
- let ( start, end) = serialized_dep_graph. edge_list_indices [ node_index] ;
175
- let targets =
176
- ( & serialized_dep_graph. edge_list_data [ start as usize .. end as usize ] )
177
- . into_iter ( )
178
- . map ( |& node_index| serialized_dep_graph. nodes [ node_index] . clone ( ) )
179
- . collect ( ) ;
180
-
181
- edge_map. insert ( source. clone ( ) , targets) ;
182
- }
183
-
184
- edge_map
185
- } ;
186
-
187
169
// Compute the set of nodes from the old graph where some input
188
- // has changed or been removed. These are "raw" source nodes,
189
- // which means that they still use the original `DefPathIndex`
190
- // values from the encoding, rather than having been retraced to a
191
- // `DefId`. The reason for this is that this way we can include
192
- // nodes that have been removed (which no longer have a `DefId` in
193
- // the current compilation).
170
+ // has changed or been removed.
194
171
let dirty_raw_nodes = initial_dirty_nodes ( tcx,
195
172
incremental_hashes_map,
173
+ & serialized_dep_graph. nodes ,
196
174
& serialized_dep_graph. hashes ) ;
197
- let dirty_raw_nodes = transitive_dirty_nodes ( & edge_map, dirty_raw_nodes) ;
175
+ let dirty_raw_nodes = transitive_dirty_nodes ( & serialized_dep_graph,
176
+ dirty_raw_nodes) ;
198
177
199
178
// Recreate the edges in the graph that are still clean.
200
179
let mut clean_work_products = FxHashSet ( ) ;
201
180
let mut dirty_work_products = FxHashSet ( ) ; // incomplete; just used to suppress debug output
202
- for ( source, targets) in & edge_map {
203
- for target in targets {
204
- process_edge ( tcx, source, target, & dirty_raw_nodes,
205
- & mut clean_work_products, & mut dirty_work_products) ;
181
+ for ( source, targets) in serialized_dep_graph. edge_list_indices . iter_enumerated ( ) {
182
+ let target_begin = targets. 0 as usize ;
183
+ let target_end = targets. 1 as usize ;
184
+
185
+ for & target in & serialized_dep_graph. edge_list_data [ target_begin .. target_end] {
186
+ process_edge ( tcx,
187
+ source,
188
+ target,
189
+ & serialized_dep_graph. nodes ,
190
+ & dirty_raw_nodes,
191
+ & mut clean_work_products,
192
+ & mut dirty_work_products) ;
206
193
}
207
194
}
208
195
209
- // Recreate bootstrap outputs, which are outputs that have no incoming edges (and hence cannot
210
- // be dirty).
196
+ // Recreate bootstrap outputs, which are outputs that have no incoming edges
197
+ // (and hence cannot be dirty).
211
198
for bootstrap_output in & serialized_dep_graph. bootstrap_outputs {
212
199
if let DepKind :: WorkProduct = bootstrap_output. kind {
213
200
let wp_id = WorkProductId :: from_fingerprint ( bootstrap_output. hash ) ;
@@ -225,7 +212,9 @@ pub fn decode_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
225
212
// dirty.
226
213
reconcile_work_products ( tcx, work_products, & clean_work_products) ;
227
214
228
- dirty_clean:: check_dirty_clean_annotations ( tcx, & dirty_raw_nodes) ;
215
+ dirty_clean:: check_dirty_clean_annotations ( tcx,
216
+ & serialized_dep_graph. nodes ,
217
+ & dirty_raw_nodes) ;
229
218
230
219
load_prev_metadata_hashes ( tcx,
231
220
& mut * incremental_hashes_map. prev_metadata_hashes . borrow_mut ( ) ) ;
@@ -236,19 +225,20 @@ pub fn decode_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
236
225
/// a bit vector where the index is the DefPathIndex.
237
226
fn initial_dirty_nodes < ' a , ' tcx > ( tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
238
227
incremental_hashes_map : & IncrementalHashesMap ,
239
- serialized_hashes : & [ SerializedHash ] )
228
+ nodes : & IndexVec < DepNodeIndex , DepNode > ,
229
+ serialized_hashes : & [ ( DepNodeIndex , Fingerprint ) ] )
240
230
-> DirtyNodes {
241
231
let mut hcx = HashContext :: new ( tcx, incremental_hashes_map) ;
242
232
let mut dirty_nodes = FxHashMap ( ) ;
243
233
244
- for hash in serialized_hashes {
245
- let dep_node = hash . dep_node ;
234
+ for & ( dep_node_index , prev_hash ) in serialized_hashes {
235
+ let dep_node = nodes [ dep_node_index ] ;
246
236
if does_still_exist ( tcx, & dep_node) {
247
237
let current_hash = hcx. hash ( & dep_node) . unwrap_or_else ( || {
248
238
bug ! ( "Cannot find current ICH for input that still exists?" )
249
239
} ) ;
250
240
251
- if current_hash == hash . hash {
241
+ if current_hash == prev_hash {
252
242
debug ! ( "initial_dirty_nodes: {:?} is clean (hash={:?})" ,
253
243
dep_node,
254
244
current_hash) ;
@@ -259,44 +249,41 @@ fn initial_dirty_nodes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
259
249
println ! ( "node {:?} is dirty as hash is {:?}, was {:?}" ,
260
250
dep_node,
261
251
current_hash,
262
- hash . hash ) ;
252
+ prev_hash ) ;
263
253
}
264
254
265
255
debug ! ( "initial_dirty_nodes: {:?} is dirty as hash is {:?}, was {:?}" ,
266
256
dep_node,
267
257
current_hash,
268
- hash . hash ) ;
258
+ prev_hash ) ;
269
259
} else {
270
260
if tcx. sess . opts . debugging_opts . incremental_dump_hash {
271
261
println ! ( "node {:?} is dirty as it was removed" , dep_node) ;
272
262
}
273
263
274
264
debug ! ( "initial_dirty_nodes: {:?} is dirty as it was removed" , dep_node) ;
275
265
}
276
-
277
- dirty_nodes. insert ( hash. dep_node . clone ( ) , hash. dep_node . clone ( ) ) ;
266
+ dirty_nodes. insert ( dep_node_index, dep_node_index) ;
278
267
}
279
268
280
269
dirty_nodes
281
270
}
282
271
283
- fn transitive_dirty_nodes ( edge_map : & FxHashMap < DepNode , Vec < DepNode > > ,
272
+ fn transitive_dirty_nodes ( serialized_dep_graph : & SerializedDepGraph ,
284
273
mut dirty_nodes : DirtyNodes )
285
274
-> DirtyNodes
286
275
{
287
- let mut stack: Vec < ( DepNode , DepNode ) > = vec ! [ ] ;
288
- stack. extend ( dirty_nodes. iter ( ) . map ( |( s, b) | ( s. clone ( ) , b. clone ( ) ) ) ) ;
276
+ let mut stack: Vec < ( DepNodeIndex , DepNodeIndex ) > = vec ! [ ] ;
277
+ stack. extend ( dirty_nodes. iter ( ) . map ( |( & s, & b) | ( s, b) ) ) ;
289
278
while let Some ( ( source, blame) ) = stack. pop ( ) {
290
279
// we know the source is dirty (because of the node `blame`)...
291
- assert ! ( dirty_nodes. contains_key( & source) ) ;
280
+ debug_assert ! ( dirty_nodes. contains_key( & source) ) ;
292
281
293
282
// ...so we dirty all the targets (with the same blame)
294
- if let Some ( targets) = edge_map. get ( & source) {
295
- for target in targets {
296
- if !dirty_nodes. contains_key ( target) {
297
- dirty_nodes. insert ( target. clone ( ) , blame. clone ( ) ) ;
298
- stack. push ( ( target. clone ( ) , blame. clone ( ) ) ) ;
299
- }
283
+ for & target in serialized_dep_graph. edge_targets_from ( source) {
284
+ if !dirty_nodes. contains_key ( & target) {
285
+ dirty_nodes. insert ( target, blame) ;
286
+ stack. push ( ( target, blame) ) ;
300
287
}
301
288
}
302
289
}
@@ -402,16 +389,18 @@ fn load_prev_metadata_hashes(tcx: TyCtxt,
402
389
403
390
fn process_edge < ' a , ' tcx , ' edges > (
404
391
tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
405
- source : & ' edges DepNode ,
406
- target : & ' edges DepNode ,
392
+ source : DepNodeIndex ,
393
+ target : DepNodeIndex ,
394
+ nodes : & IndexVec < DepNodeIndex , DepNode > ,
407
395
dirty_raw_nodes : & DirtyNodes ,
408
396
clean_work_products : & mut FxHashSet < WorkProductId > ,
409
397
dirty_work_products : & mut FxHashSet < WorkProductId > )
410
398
{
411
399
// If the target is dirty, skip the edge. If this is an edge
412
400
// that targets a work-product, we can print the blame
413
401
// information now.
414
- if let Some ( blame) = dirty_raw_nodes. get ( target) {
402
+ if let Some ( & blame) = dirty_raw_nodes. get ( & target) {
403
+ let target = nodes[ target] ;
415
404
if let DepKind :: WorkProduct = target. kind {
416
405
if tcx. sess . opts . debugging_opts . incremental_info {
417
406
let wp_id = WorkProductId :: from_fingerprint ( target. hash ) ;
@@ -420,6 +409,7 @@ fn process_edge<'a, 'tcx, 'edges>(
420
409
// Try to reconstruct the human-readable version of the
421
410
// DepNode. This cannot be done for things that where
422
411
// removed.
412
+ let blame = nodes[ blame] ;
423
413
let blame_str = if let Some ( def_id) = blame. extract_def_id ( tcx) {
424
414
format ! ( "{:?}({})" ,
425
415
blame. kind,
@@ -444,21 +434,23 @@ fn process_edge<'a, 'tcx, 'edges>(
444
434
445
435
// We should never have an edge where the target is clean but the source
446
436
// was dirty. Otherwise something was wrong with the dirtying pass above:
447
- debug_assert ! ( !dirty_raw_nodes. contains_key( source) ) ;
437
+ debug_assert ! ( !dirty_raw_nodes. contains_key( & source) ) ;
448
438
449
439
// We also never should encounter an edge going from a removed input to a
450
440
// clean target because removing the input would have dirtied the input
451
441
// node and transitively dirtied the target.
452
- debug_assert ! ( match source. kind {
442
+ debug_assert ! ( match nodes [ source] . kind {
453
443
DepKind :: Hir | DepKind :: HirBody | DepKind :: MetaData => {
454
- does_still_exist( tcx, source)
444
+ does_still_exist( tcx, & nodes [ source] )
455
445
}
456
446
_ => true ,
457
447
} ) ;
458
448
459
- if !dirty_raw_nodes. contains_key ( target) {
460
- let _task = tcx. dep_graph . in_task ( * target) ;
461
- tcx. dep_graph . read ( * source) ;
449
+ if !dirty_raw_nodes. contains_key ( & target) {
450
+ let target = nodes[ target] ;
451
+ let source = nodes[ source] ;
452
+ let _task = tcx. dep_graph . in_task ( target) ;
453
+ tcx. dep_graph . read ( source) ;
462
454
463
455
if let DepKind :: WorkProduct = target. kind {
464
456
let wp_id = WorkProductId :: from_fingerprint ( target. hash ) ;
0 commit comments