Skip to content

Commit 000d3c9

Browse files
committed
Make DepGraph::previous_work_products immutable
Fixes #50501
1 parent 565235e commit 000d3c9

File tree

3 files changed

+74
-83
lines changed

3 files changed

+74
-83
lines changed

src/librustc/dep_graph/graph.rs

+7-19
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ struct DepGraphData {
7777
/// things available to us. If we find that they are not dirty, we
7878
/// load the path to the file storing those work-products here into
7979
/// this map. We can later look for and extract that data.
80-
previous_work_products: RwLock<FxHashMap<WorkProductId, WorkProduct>>,
80+
previous_work_products: FxHashMap<WorkProductId, WorkProduct>,
8181

8282
/// Work-products that we generate in this run.
8383
work_products: RwLock<FxHashMap<WorkProductId, WorkProduct>>,
@@ -90,7 +90,8 @@ struct DepGraphData {
9090

9191
impl DepGraph {
9292

93-
pub fn new(prev_graph: PreviousDepGraph) -> DepGraph {
93+
pub fn new(prev_graph: PreviousDepGraph,
94+
prev_work_products: FxHashMap<WorkProductId, WorkProduct>) -> DepGraph {
9495
// Pre-allocate the fingerprints array. We over-allocate a little so
9596
// that we hopefully don't have to re-allocate during this compilation
9697
// session.
@@ -100,7 +101,7 @@ impl DepGraph {
100101
(prev_graph_node_count * 115) / 100);
101102
DepGraph {
102103
data: Some(Lrc::new(DepGraphData {
103-
previous_work_products: RwLock::new(FxHashMap()),
104+
previous_work_products: prev_work_products,
104105
work_products: RwLock::new(FxHashMap()),
105106
dep_node_debug: Lock::new(FxHashMap()),
106107
current: Lock::new(CurrentDepGraph::new()),
@@ -460,19 +461,6 @@ impl DepGraph {
460461
self.data.as_ref().unwrap().previous.node_to_index(dep_node)
461462
}
462463

463-
/// Indicates that a previous work product exists for `v`. This is
464-
/// invoked during initial start-up based on what nodes are clean
465-
/// (and what files exist in the incr. directory).
466-
pub fn insert_previous_work_product(&self, v: &WorkProductId, data: WorkProduct) {
467-
debug!("insert_previous_work_product({:?}, {:?})", v, data);
468-
self.data
469-
.as_ref()
470-
.unwrap()
471-
.previous_work_products
472-
.borrow_mut()
473-
.insert(v.clone(), data);
474-
}
475-
476464
/// Indicates that we created the given work-product in this run
477465
/// for `v`. This record will be preserved and loaded in the next
478466
/// run.
@@ -492,7 +480,7 @@ impl DepGraph {
492480
self.data
493481
.as_ref()
494482
.and_then(|data| {
495-
data.previous_work_products.borrow().get(v).cloned()
483+
data.previous_work_products.get(v).cloned()
496484
})
497485
}
498486

@@ -504,8 +492,8 @@ impl DepGraph {
504492

505493
/// Access the map of work-products created during the cached run. Only
506494
/// used during saving of the dep-graph.
507-
pub fn previous_work_products(&self) -> ReadGuard<FxHashMap<WorkProductId, WorkProduct>> {
508-
self.data.as_ref().unwrap().previous_work_products.borrow()
495+
pub fn previous_work_products(&self) -> &FxHashMap<WorkProductId, WorkProduct> {
496+
&self.data.as_ref().unwrap().previous_work_products
509497
}
510498

511499
#[inline(always)]

src/librustc_driver/driver.rs

+10-9
Original file line numberDiff line numberDiff line change
@@ -980,15 +980,16 @@ where
980980
let dep_graph = match future_dep_graph {
981981
None => DepGraph::new_disabled(),
982982
Some(future) => {
983-
let prev_graph = time(sess, "blocked while dep-graph loading finishes", || {
984-
future
985-
.open()
986-
.unwrap_or_else(|e| rustc_incremental::LoadResult::Error {
987-
message: format!("could not decode incremental cache: {:?}", e),
988-
})
989-
.open(sess)
990-
});
991-
DepGraph::new(prev_graph)
983+
let (prev_graph, prev_work_products) =
984+
time(sess, "blocked while dep-graph loading finishes", || {
985+
future
986+
.open()
987+
.unwrap_or_else(|e| rustc_incremental::LoadResult::Error {
988+
message: format!("could not decode incremental cache: {:?}", e),
989+
})
990+
.open(sess)
991+
});
992+
DepGraph::new(prev_graph, prev_work_products)
992993
}
993994
};
994995
let hir_forest = time(sess, "lowering ast -> hir", || {

src/librustc_incremental/persist/load.rs

+57-55
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@
1010

1111
//! Code to save/load the dep-graph from files.
1212
13-
use rustc::dep_graph::{PreviousDepGraph, SerializedDepGraph};
13+
use rustc_data_structures::fx::FxHashMap;
14+
use rustc::dep_graph::{PreviousDepGraph, SerializedDepGraph, WorkProduct, WorkProductId};
1415
use rustc::session::Session;
1516
use rustc::ty::TyCtxt;
1617
use rustc::ty::maps::OnDiskCache;
@@ -32,73 +33,30 @@ pub fn dep_graph_tcx_init<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
3233

3334
tcx.allocate_metadata_dep_nodes();
3435
tcx.precompute_in_scope_traits_hashes();
35-
36-
if tcx.sess.incr_comp_session_dir_opt().is_none() {
37-
// If we are only building with -Zquery-dep-graph but without an actual
38-
// incr. comp. session directory, we exit here. Otherwise we'd fail
39-
// when trying to load work products.
40-
return
41-
}
42-
43-
let work_products_path = work_products_path(tcx.sess);
44-
let load_result = load_data(tcx.sess.opts.debugging_opts.incremental_info, &work_products_path);
45-
46-
if let LoadResult::Ok { data: (work_products_data, start_pos) } = load_result {
47-
// Decode the list of work_products
48-
let mut work_product_decoder = Decoder::new(&work_products_data[..], start_pos);
49-
let work_products: Vec<SerializedWorkProduct> =
50-
RustcDecodable::decode(&mut work_product_decoder).unwrap_or_else(|e| {
51-
let msg = format!("Error decoding `work-products` from incremental \
52-
compilation session directory: {}", e);
53-
tcx.sess.fatal(&msg[..])
54-
});
55-
56-
for swp in work_products {
57-
let mut all_files_exist = true;
58-
for &(_, ref file_name) in swp.work_product.saved_files.iter() {
59-
let path = in_incr_comp_dir_sess(tcx.sess, file_name);
60-
if !path.exists() {
61-
all_files_exist = false;
62-
63-
if tcx.sess.opts.debugging_opts.incremental_info {
64-
eprintln!("incremental: could not find file for work \
65-
product: {}", path.display());
66-
}
67-
}
68-
}
69-
70-
if all_files_exist {
71-
debug!("reconcile_work_products: all files for {:?} exist", swp);
72-
tcx.dep_graph.insert_previous_work_product(&swp.id, swp.work_product);
73-
} else {
74-
debug!("reconcile_work_products: some file for {:?} does not exist", swp);
75-
delete_dirty_work_product(tcx, swp);
76-
}
77-
}
78-
}
7936
}
8037

38+
type WorkProductMap = FxHashMap<WorkProductId, WorkProduct>;
39+
8140
pub enum LoadResult<T> {
8241
Ok { data: T },
8342
DataOutOfDate,
8443
Error { message: String },
8544
}
8645

87-
88-
impl LoadResult<PreviousDepGraph> {
89-
pub fn open(self, sess: &Session) -> PreviousDepGraph {
46+
impl LoadResult<(PreviousDepGraph, WorkProductMap)> {
47+
pub fn open(self, sess: &Session) -> (PreviousDepGraph, WorkProductMap) {
9048
match self {
9149
LoadResult::Error { message } => {
9250
sess.warn(&message);
93-
PreviousDepGraph::new(SerializedDepGraph::new())
51+
(PreviousDepGraph::new(SerializedDepGraph::new()), FxHashMap())
9452
},
9553
LoadResult::DataOutOfDate => {
9654
if let Err(err) = delete_all_session_dir_contents(sess) {
9755
sess.err(&format!("Failed to delete invalidated or incompatible \
9856
incremental compilation session directory contents `{}`: {}.",
9957
dep_graph_path(sess).display(), err));
10058
}
101-
PreviousDepGraph::new(SerializedDepGraph::new())
59+
(PreviousDepGraph::new(SerializedDepGraph::new()), FxHashMap())
10260
}
10361
LoadResult::Ok { data } => data
10462
}
@@ -125,10 +83,10 @@ fn load_data(report_incremental_info: bool, path: &Path) -> LoadResult<(Vec<u8>,
12583
}
12684
}
12785

128-
fn delete_dirty_work_product(tcx: TyCtxt,
86+
fn delete_dirty_work_product(sess: &Session,
12987
swp: SerializedWorkProduct) {
13088
debug!("delete_dirty_work_product({:?})", swp);
131-
work_product::delete_workproduct_files(tcx.sess, &swp.work_product);
89+
work_product::delete_workproduct_files(sess, &swp.work_product);
13290
}
13391

13492
/// Either a result that has already be computed or a
@@ -149,7 +107,7 @@ impl<T> MaybeAsync<T> {
149107

150108
/// Launch a thread and load the dependency graph in the background.
151109
pub fn load_dep_graph(sess: &Session) ->
152-
MaybeAsync<LoadResult<PreviousDepGraph>>
110+
MaybeAsync<LoadResult<(PreviousDepGraph, WorkProductMap)>>
153111
{
154112
// Since `sess` isn't `Sync`, we perform all accesses to `sess`
155113
// before we fire the background thread.
@@ -159,7 +117,7 @@ pub fn load_dep_graph(sess: &Session) ->
159117
if sess.opts.incremental.is_none() {
160118
// No incremental compilation.
161119
return MaybeAsync::Sync(LoadResult::Ok {
162-
data: PreviousDepGraph::new(SerializedDepGraph::new())
120+
data: (PreviousDepGraph::new(SerializedDepGraph::new()), FxHashMap())
163121
});
164122
}
165123

@@ -169,6 +127,50 @@ pub fn load_dep_graph(sess: &Session) ->
169127
let report_incremental_info = sess.opts.debugging_opts.incremental_info;
170128
let expected_hash = sess.opts.dep_tracking_hash();
171129

130+
let mut prev_work_products = FxHashMap();
131+
132+
// If we are only building with -Zquery-dep-graph but without an actual
133+
// incr. comp. session directory, we exit here. Otherwise we'd fail
134+
// when trying to load work products.
135+
if sess.incr_comp_session_dir_opt().is_some() {
136+
let work_products_path = work_products_path(sess);
137+
let load_result = load_data(report_incremental_info, &work_products_path);
138+
139+
if let LoadResult::Ok { data: (work_products_data, start_pos) } = load_result {
140+
// Decode the list of work_products
141+
let mut work_product_decoder = Decoder::new(&work_products_data[..], start_pos);
142+
let work_products: Vec<SerializedWorkProduct> =
143+
RustcDecodable::decode(&mut work_product_decoder).unwrap_or_else(|e| {
144+
let msg = format!("Error decoding `work-products` from incremental \
145+
compilation session directory: {}", e);
146+
sess.fatal(&msg[..])
147+
});
148+
149+
for swp in work_products {
150+
let mut all_files_exist = true;
151+
for &(_, ref file_name) in swp.work_product.saved_files.iter() {
152+
let path = in_incr_comp_dir_sess(sess, file_name);
153+
if !path.exists() {
154+
all_files_exist = false;
155+
156+
if sess.opts.debugging_opts.incremental_info {
157+
eprintln!("incremental: could not find file for work \
158+
product: {}", path.display());
159+
}
160+
}
161+
}
162+
163+
if all_files_exist {
164+
debug!("reconcile_work_products: all files for {:?} exist", swp);
165+
prev_work_products.insert(swp.id, swp.work_product);
166+
} else {
167+
debug!("reconcile_work_products: some file for {:?} does not exist", swp);
168+
delete_dirty_work_product(sess, swp);
169+
}
170+
}
171+
}
172+
}
173+
172174
MaybeAsync::Async(std::thread::spawn(move || {
173175
time_ext(time_passes, None, "background load prev dep-graph", move || {
174176
match load_data(report_incremental_info, &path) {
@@ -195,7 +197,7 @@ pub fn load_dep_graph(sess: &Session) ->
195197
let dep_graph = SerializedDepGraph::decode(&mut decoder)
196198
.expect("Error reading cached dep-graph");
197199

198-
LoadResult::Ok { data: PreviousDepGraph::new(dep_graph) }
200+
LoadResult::Ok { data: (PreviousDepGraph::new(dep_graph), prev_work_products) }
199201
}
200202
}
201203
})

0 commit comments

Comments
 (0)