Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

detect "bootstrap outputs" when serializing the dep-graph #40038

Merged
merged 1 commit into from
Feb 25, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/librustc_incremental/persist/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ use super::directory::DefPathIndex;
pub struct SerializedDepGraph {
pub edges: Vec<SerializedEdgeSet>,

/// These are output nodes that have no incoming edges. We track
/// these separately so that when we reload all edges, we don't
/// lose track of these nodes.
pub bootstrap_outputs: Vec<DepNode<DefPathIndex>>,

/// These are hashes of two things:
/// - the HIR nodes in this crate
/// - the metadata nodes from dependent crates we use
Expand Down
12 changes: 12 additions & 0 deletions src/librustc_incremental/persist/load.rs
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,18 @@ pub fn decode_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
}
}

// Recreate bootstrap outputs, which are outputs that have no incoming edges (and hence cannot
// be dirty).
for bootstrap_output in &serialized_dep_graph.bootstrap_outputs {
if let Some(n) = retraced.map(bootstrap_output) {
if let DepNode::WorkProduct(ref wp) = n {
clean_work_products.insert(wp.clone());
}

tcx.dep_graph.with_task(n, || ()); // create the node with no inputs
}
}

// Subtle. Sometimes we have intermediate nodes that we can't recreate in the new graph.
// This is pretty unusual but it arises in a scenario like this:
//
Expand Down
21 changes: 19 additions & 2 deletions src/librustc_incremental/persist/preds/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
use rustc::dep_graph::{DepGraphQuery, DepNode};
use rustc::hir::def_id::DefId;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::graph::Graph;
use rustc_data_structures::graph::{Graph, NodeIndex};

use super::hash::*;
use ich::Fingerprint;
Expand All @@ -28,6 +28,14 @@ pub struct Predecessors<'query> {
// of the graph down.
pub reduced_graph: Graph<&'query DepNode<DefId>, ()>,

// These are output nodes that have no incoming edges. We have to
// track these specially because, when we load the data back up
// again, we want to make sure and recreate these nodes (we want
// to recreate the nodes where all incoming edges are clean; but
// since we ordinarily just serialize edges, we wind up just
// forgetting that bootstrap outputs even exist in that case.)
pub bootstrap_outputs: Vec<&'query DepNode<DefId>>,

// For the inputs (hir/foreign-metadata), we include hashes.
pub hashes: FxHashMap<&'query DepNode<DefId>, Fingerprint>,
}
Expand Down Expand Up @@ -57,7 +65,7 @@ impl<'q> Predecessors<'q> {

// Reduce the graph to the most important nodes.
let compress::Reduction { graph, input_nodes } =
compress::reduce_graph(&query.graph, HashContext::is_hashable, is_output);
compress::reduce_graph(&query.graph, HashContext::is_hashable, |n| is_output(n));

let mut hashes = FxHashMap();
for input_index in input_nodes {
Expand All @@ -67,8 +75,17 @@ impl<'q> Predecessors<'q> {
.or_insert_with(|| hcx.hash(input).unwrap());
}

let bootstrap_outputs: Vec<&'q DepNode<DefId>> =
(0 .. graph.len_nodes())
.map(NodeIndex)
.filter(|&n| graph.incoming_edges(n).next().is_none())
.map(|n| *graph.node_data(n))
.filter(|n| is_output(n))
.collect();

Predecessors {
reduced_graph: graph,
bootstrap_outputs: bootstrap_outputs,
hashes: hashes,
}
}
Expand Down
7 changes: 6 additions & 1 deletion src/librustc_incremental/persist/save.rs
Original file line number Diff line number Diff line change
Expand Up @@ -204,11 +204,15 @@ pub fn encode_dep_graph(preds: &Predecessors,
}

// Create the serialized dep-graph.
let bootstrap_outputs = preds.bootstrap_outputs.iter()
.map(|n| builder.map(n))
.collect();
let edges = edges.into_iter()
.map(|(k, v)| SerializedEdgeSet { source: k, targets: v })
.collect();
let graph = SerializedDepGraph {
edges: edges,
bootstrap_outputs,
edges,
hashes: preds.hashes
.iter()
.map(|(&dep_node, &hash)| {
Expand All @@ -221,6 +225,7 @@ pub fn encode_dep_graph(preds: &Predecessors,
};

if tcx.sess.opts.debugging_opts.incremental_info {
println!("incremental: {} nodes in reduced dep-graph", preds.reduced_graph.len_nodes());
println!("incremental: {} edges in serialized dep-graph", graph.edges.len());
println!("incremental: {} hashes in serialized dep-graph", graph.hashes.len());
}
Expand Down
18 changes: 18 additions & 0 deletions src/test/incremental/issue-39828/auxiliary/generic.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// revisions:rpass1 rpass2
// compile-flags: -Z query-dep-graph

#![rustc_partition_reused(module="__rustc_fallback_codegen_unit", cfg="rpass2")]
#![feature(rustc_attrs)]

#![crate_type="rlib"]
pub fn foo<T>() { }
22 changes: 22 additions & 0 deletions src/test/incremental/issue-39828/issue-39828.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// Regression test for #39828. If you make use of a module that
// consists only of generics, no code is generated, just a dummy
// module. The reduced graph consists of a single node (for that
// module) with no inputs. Since we only serialize edges, when we
// reload, we would consider that node dirty since it is not recreated
// (it is not the target of any edges).

// revisions:rpass1 rpass2
// aux-build:generic.rs

extern crate generic;
fn main() { }