@@ -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