Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit d1d8258

Browse files
committedAug 19, 2016
Implement copy-on-write scheme for managing the incremental compilation cache.
1 parent a2ff0e2 commit d1d8258

File tree

14 files changed

+1161
-151
lines changed

14 files changed

+1161
-151
lines changed
 

‎src/librustc/hir/svh.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
1818
use std::fmt;
1919
use std::hash::{Hash, Hasher};
20+
use serialize::{Encodable, Decodable, Encoder, Decoder};
2021

2122
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
2223
pub struct Svh {
@@ -51,3 +52,17 @@ impl fmt::Display for Svh {
5152
f.pad(&self.to_string())
5253
}
5354
}
55+
56+
impl Encodable for Svh {
57+
fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
58+
s.emit_u64(self.as_u64().to_le())
59+
}
60+
}
61+
62+
impl Decodable for Svh {
63+
fn decode<D: Decoder>(d: &mut D) -> Result<Svh, D::Error> {
64+
d.read_u64()
65+
.map(u64::from_le)
66+
.map(Svh::new)
67+
}
68+
}

‎src/librustc/session/mod.rs

Lines changed: 92 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,11 @@ use syntax::feature_gate::AttributeType;
3333
use syntax_pos::{Span, MultiSpan};
3434

3535
use rustc_back::target::Target;
36+
use rustc_data_structures::flock;
3637
use llvm;
3738

3839
use std::path::{Path, PathBuf};
39-
use std::cell::{Cell, RefCell};
40+
use std::cell::{self, Cell, RefCell};
4041
use std::collections::{HashMap, HashSet};
4142
use std::env;
4243
use std::ffi::CString;
@@ -101,6 +102,8 @@ pub struct Session {
101102
/// macro name and defintion span in the source crate.
102103
pub imported_macro_spans: RefCell<HashMap<Span, (String, Span)>>,
103104

105+
incr_comp_session: RefCell<IncrCompSession>,
106+
104107
next_node_id: Cell<ast::NodeId>,
105108
}
106109

@@ -331,6 +334,70 @@ impl Session {
331334
&self.opts.search_paths,
332335
kind)
333336
}
337+
338+
pub fn init_incr_comp_session(&self,
339+
session_dir: PathBuf,
340+
lock_file: flock::Lock) {
341+
let mut incr_comp_session = self.incr_comp_session.borrow_mut();
342+
343+
if let IncrCompSession::NotInitialized = *incr_comp_session { } else {
344+
bug!("Trying to initialize IncrCompSession `{:?}`", *incr_comp_session)
345+
}
346+
347+
*incr_comp_session = IncrCompSession::Active {
348+
session_directory: session_dir,
349+
lock_file: lock_file,
350+
};
351+
}
352+
353+
pub fn finalize_incr_comp_session(&self, new_directory_path: PathBuf) {
354+
let mut incr_comp_session = self.incr_comp_session.borrow_mut();
355+
356+
if let IncrCompSession::Active { .. } = *incr_comp_session { } else {
357+
bug!("Trying to finalize IncrCompSession `{:?}`", *incr_comp_session)
358+
}
359+
360+
// Note: This will also drop the lock file, thus unlocking the directory
361+
*incr_comp_session = IncrCompSession::Finalized {
362+
session_directory: new_directory_path,
363+
};
364+
}
365+
366+
pub fn mark_incr_comp_session_as_invalid(&self) {
367+
let mut incr_comp_session = self.incr_comp_session.borrow_mut();
368+
369+
if let IncrCompSession::Active { .. } = *incr_comp_session { } else {
370+
bug!("Trying to invalidate IncrCompSession `{:?}`", *incr_comp_session)
371+
}
372+
373+
// Note: This will also drop the lock file, thus unlocking the directory
374+
*incr_comp_session = IncrCompSession::InvalidBecauseOfErrors;
375+
}
376+
377+
pub fn incr_comp_session_dir(&self) -> cell::Ref<PathBuf> {
378+
let incr_comp_session = self.incr_comp_session.borrow();
379+
cell::Ref::map(incr_comp_session, |incr_comp_session| {
380+
match *incr_comp_session {
381+
IncrCompSession::NotInitialized |
382+
IncrCompSession::InvalidBecauseOfErrors => {
383+
bug!("Trying to get session directory from IncrCompSession `{:?}`",
384+
*incr_comp_session)
385+
}
386+
IncrCompSession::Active { ref session_directory, .. } |
387+
IncrCompSession::Finalized { ref session_directory } => {
388+
session_directory
389+
}
390+
}
391+
})
392+
}
393+
394+
pub fn incr_comp_session_dir_opt(&self) -> Option<cell::Ref<PathBuf>> {
395+
if self.opts.incremental.is_some() {
396+
Some(self.incr_comp_session_dir())
397+
} else {
398+
None
399+
}
400+
}
334401
}
335402

336403
pub fn build_session(sopts: config::Options,
@@ -446,13 +513,37 @@ pub fn build_session_(sopts: config::Options,
446513
injected_panic_runtime: Cell::new(None),
447514
available_macros: RefCell::new(HashSet::new()),
448515
imported_macro_spans: RefCell::new(HashMap::new()),
516+
incr_comp_session: RefCell::new(IncrCompSession::NotInitialized),
449517
};
450518

451519
init_llvm(&sess);
452520

453521
sess
454522
}
455523

524+
/// Holds data on the current incremental compilation session, if there is one.
525+
#[derive(Debug)]
526+
pub enum IncrCompSession {
527+
// This is the state the session will be in until the incr. comp. dir is
528+
// needed.
529+
NotInitialized,
530+
// This is the state during which the session directory is private and can
531+
// be modified.
532+
Active {
533+
session_directory: PathBuf,
534+
lock_file: flock::Lock,
535+
},
536+
// This is the state after the session directory has been finalized. In this
537+
// state, the contents of the directory must not be modified any more.
538+
Finalized {
539+
session_directory: PathBuf,
540+
},
541+
// This is an error state that is reached when some compilation error has
542+
// occurred. It indicates that the contents of the session directory must
543+
// not be used, since they might be invalid.
544+
InvalidBecauseOfErrors,
545+
}
546+
456547
fn init_llvm(sess: &Session) {
457548
unsafe {
458549
// Before we touch LLVM, make sure that multithreading is enabled.

‎src/librustc/util/fs.rs

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,14 +56,49 @@ pub fn fix_windows_verbatim_for_gcc(p: &Path) -> PathBuf {
5656
}
5757
}
5858

59+
pub enum LinkOrCopy {
60+
Link,
61+
Copy
62+
}
63+
5964
/// Copy `p` into `q`, preferring to use hard-linking if possible. If
6065
/// `q` already exists, it is removed first.
61-
pub fn link_or_copy<P: AsRef<Path>, Q: AsRef<Path>>(p: P, q: Q) -> io::Result<()> {
66+
/// The result indicates which of the two operations has been performed.
67+
pub fn link_or_copy<P: AsRef<Path>, Q: AsRef<Path>>(p: P, q: Q) -> io::Result<LinkOrCopy> {
6268
let p = p.as_ref();
6369
let q = q.as_ref();
6470
if q.exists() {
6571
try!(fs::remove_file(&q));
6672
}
67-
fs::hard_link(p, q)
68-
.or_else(|_| fs::copy(p, q).map(|_| ()))
73+
74+
match fs::hard_link(p, q) {
75+
Ok(()) => Ok(LinkOrCopy::Link),
76+
Err(_) => {
77+
match fs::copy(p, q) {
78+
Ok(_) => Ok(LinkOrCopy::Copy),
79+
Err(e) => Err(e)
80+
}
81+
}
82+
}
83+
}
84+
85+
// Like std::fs::create_dir_all, except handles concurrent calls among multiple
86+
// threads or processes.
87+
pub fn create_dir_racy(path: &Path) -> io::Result<()> {
88+
match fs::create_dir(path) {
89+
Ok(()) => return Ok(()),
90+
Err(ref e) if e.kind() == io::ErrorKind::AlreadyExists => return Ok(()),
91+
Err(ref e) if e.kind() == io::ErrorKind::NotFound => {}
92+
Err(e) => return Err(e),
93+
}
94+
match path.parent() {
95+
Some(p) => try!(create_dir_racy(p)),
96+
None => return Err(io::Error::new(io::ErrorKind::Other,
97+
"failed to create whole tree")),
98+
}
99+
match fs::create_dir(path) {
100+
Ok(()) => Ok(()),
101+
Err(ref e) if e.kind() == io::ErrorKind::AlreadyExists => Ok(()),
102+
Err(e) => Err(e),
103+
}
69104
}

‎src/librustc_data_structures/flock.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ mod imp {
136136
pub const F_SETLKW: libc::c_int = 7;
137137
}
138138

139+
#[derive(Debug)]
139140
pub struct Lock {
140141
fd: libc::c_int,
141142
}
@@ -251,6 +252,7 @@ mod imp {
251252
lpOverlapped: LPOVERLAPPED) -> BOOL;
252253
}
253254

255+
#[derive(Debug)]
254256
pub struct Lock {
255257
_file: File,
256258
}

‎src/librustc_driver/driver.rs

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ pub fn compile_input(sess: &Session,
8888
// We need nested scopes here, because the intermediate results can keep
8989
// large chunks of memory alive and we want to free them as soon as
9090
// possible to keep the peak memory usage low
91-
let (outputs, trans, crate_name) = {
91+
let (outputs, trans) = {
9292
let krate = match phase_1_parse_input(sess, cfg, input) {
9393
Ok(krate) => krate,
9494
Err(mut parse_error) => {
@@ -212,11 +212,11 @@ pub fn compile_input(sess: &Session,
212212
// Discard interned strings as they are no longer required.
213213
token::clear_ident_interner();
214214

215-
Ok((outputs, trans, crate_name.clone()))
215+
Ok((outputs, trans))
216216
})??
217217
};
218218

219-
let phase5_result = phase_5_run_llvm_passes(sess, &crate_name, &trans, &outputs);
219+
let phase5_result = phase_5_run_llvm_passes(sess, &trans, &outputs);
220220

221221
controller_entry_point!(after_llvm,
222222
sess,
@@ -228,6 +228,10 @@ pub fn compile_input(sess: &Session,
228228

229229
phase_6_link_output(sess, &trans, &outputs);
230230

231+
// Now that we won't touch anything in the incremental compilation directory
232+
// any more, we can finalize it (which involves renaming it)
233+
rustc_incremental::finalize_session_directory(sess, trans.link.crate_hash);
234+
231235
controller_entry_point!(compilation_done,
232236
sess,
233237
CompileState::state_when_compilation_done(input, sess, outdir, output),
@@ -1011,19 +1015,18 @@ pub fn phase_4_translate_to_llvm<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
10111015

10121016
time(time_passes,
10131017
"assert dep graph",
1014-
move || rustc_incremental::assert_dep_graph(tcx));
1018+
|| rustc_incremental::assert_dep_graph(tcx));
10151019

10161020
time(time_passes,
10171021
"serialize dep graph",
1018-
move || rustc_incremental::save_dep_graph(tcx));
1019-
1022+
|| rustc_incremental::save_dep_graph(tcx,
1023+
translation.link.crate_hash));
10201024
translation
10211025
}
10221026

10231027
/// Run LLVM itself, producing a bitcode file, assembly file or object file
10241028
/// as a side effect.
10251029
pub fn phase_5_run_llvm_passes(sess: &Session,
1026-
crate_name: &str,
10271030
trans: &trans::CrateTranslation,
10281031
outputs: &OutputFilenames) -> CompileResult {
10291032
if sess.opts.cg.no_integrated_as {
@@ -1046,7 +1049,7 @@ pub fn phase_5_run_llvm_passes(sess: &Session,
10461049

10471050
time(sess.time_passes(),
10481051
"serialize work products",
1049-
move || rustc_incremental::save_work_products(sess, crate_name));
1052+
move || rustc_incremental::save_work_products(sess));
10501053

10511054
if sess.err_count() > 0 {
10521055
Err(sess.err_count())

‎src/librustc_incremental/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#![feature(question_mark)]
2323
#![feature(rustc_private)]
2424
#![feature(staged_api)]
25+
#![feature(rand)]
2526

2627
extern crate graphviz;
2728
extern crate rbml;
@@ -44,3 +45,4 @@ pub use persist::save_dep_graph;
4445
pub use persist::save_trans_partition;
4546
pub use persist::save_work_products;
4647
pub use persist::in_incr_comp_dir;
48+
pub use persist::finalize_session_directory;

‎src/librustc_incremental/persist/fs.rs

Lines changed: 895 additions & 0 deletions
Large diffs are not rendered by default.

‎src/librustc_incremental/persist/hash.rs

Lines changed: 45 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,14 @@ use rustc::hir::def_id::DefId;
1616
use rustc::hir::svh::Svh;
1717
use rustc::ty::TyCtxt;
1818
use rustc_data_structures::fnv::FnvHashMap;
19+
use rustc_data_structures::flock;
1920
use rustc_serialize::Decodable;
2021
use std::io::{ErrorKind, Read};
2122
use std::fs::File;
2223
use syntax::ast;
2324

2425
use super::data::*;
25-
use super::util::*;
26+
use super::fs::*;
2627

2728
pub struct HashContext<'a, 'tcx: 'a> {
2829
pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
@@ -124,19 +125,43 @@ impl<'a, 'tcx> HashContext<'a, 'tcx> {
124125
debug!("load_data: svh={}", svh);
125126
assert!(old.is_none(), "loaded data for crate {:?} twice", cnum);
126127

127-
if let Some(path) = metadata_hash_path(self.tcx, cnum) {
128-
debug!("load_data: path={:?}", path);
128+
if let Some(session_dir) = find_metadata_hashes_for(self.tcx, cnum) {
129+
debug!("load_data: session_dir={:?}", session_dir);
130+
131+
// Lock the directory we'll be reading the hashes from.
132+
let lock_file_path = lock_file_path(&session_dir);
133+
let _lock = match flock::Lock::new(&lock_file_path,
134+
false, // don't wait
135+
false, // don't create the lock-file
136+
false) { // shared lock
137+
Ok(lock) => lock,
138+
Err(err) => {
139+
debug!("Could not acquire lock on `{}` while trying to \
140+
load metadata hashes: {}",
141+
lock_file_path.display(),
142+
err);
143+
144+
// Could not acquire the lock. The directory is probably in
145+
// in the process of being deleted. It's OK to just exit
146+
// here. It's the same scenario as if the file had not
147+
// existed in the first place.
148+
return
149+
}
150+
};
151+
152+
let hashes_file_path = metadata_hash_import_path(&session_dir);
153+
129154
let mut data = vec![];
130155
match
131-
File::open(&path)
132-
.and_then(|mut file| file.read_to_end(&mut data))
156+
File::open(&hashes_file_path)
157+
.and_then(|mut file| file.read_to_end(&mut data))
133158
{
134159
Ok(_) => {
135-
match self.load_from_data(cnum, &data) {
160+
match self.load_from_data(cnum, &data, svh) {
136161
Ok(()) => { }
137162
Err(err) => {
138163
bug!("decoding error in dep-graph from `{}`: {}",
139-
path.display(), err);
164+
&hashes_file_path.display(), err);
140165
}
141166
}
142167
}
@@ -148,7 +173,7 @@ impl<'a, 'tcx> HashContext<'a, 'tcx> {
148173
_ => {
149174
self.tcx.sess.err(
150175
&format!("could not load dep information from `{}`: {}",
151-
path.display(), err));
176+
hashes_file_path.display(), err));
152177
return;
153178
}
154179
}
@@ -157,11 +182,22 @@ impl<'a, 'tcx> HashContext<'a, 'tcx> {
157182
}
158183
}
159184

160-
fn load_from_data(&mut self, cnum: ast::CrateNum, data: &[u8]) -> Result<(), Error> {
185+
fn load_from_data(&mut self,
186+
cnum: ast::CrateNum,
187+
data: &[u8],
188+
expected_svh: Svh) -> Result<(), Error> {
161189
debug!("load_from_data(cnum={})", cnum);
162190

163191
// Load up the hashes for the def-ids from this crate.
164192
let mut decoder = Decoder::new(data, 0);
193+
let svh_in_hashes_file = try!(Svh::decode(&mut decoder));
194+
195+
if svh_in_hashes_file != expected_svh {
196+
// We should not be able to get here. If we do, then
197+
// `fs::find_metadata_hashes_for()` has messed up.
198+
bug!("mismatch between SVH in crate and SVH in incr. comp. hashes")
199+
}
200+
165201
let serialized_hashes = try!(SerializedMetadataHashes::decode(&mut decoder));
166202
for serialized_hash in serialized_hashes.hashes {
167203
// the hashes are stored with just a def-index, which is

‎src/librustc_incremental/persist/load.rs

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ use super::data::*;
2626
use super::directory::*;
2727
use super::dirty_clean;
2828
use super::hash::*;
29-
use super::util::*;
29+
use super::fs::*;
3030

3131
pub type DirtyNodes = FnvHashSet<DepNode<DefPathIndex>>;
3232

@@ -43,18 +43,37 @@ pub fn load_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
4343
return;
4444
}
4545

46+
match prepare_session_directory(tcx) {
47+
Ok(true) => {
48+
// We successfully allocated a session directory and there is
49+
// something in it to load, so continue
50+
}
51+
Ok(false) => {
52+
// We successfully allocated a session directory, but there is no
53+
// dep-graph data in it to load (because this is the first
54+
// compilation session with this incr. comp. dir.)
55+
return
56+
}
57+
Err(()) => {
58+
// Something went wrong while trying to allocate the session
59+
// directory. Don't try to use it any further.
60+
let _ = garbage_collect_session_directories(tcx.sess);
61+
return
62+
}
63+
}
64+
4665
let _ignore = tcx.dep_graph.in_ignore();
4766
load_dep_graph_if_exists(tcx);
4867
}
4968

5069
fn load_dep_graph_if_exists<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
51-
let dep_graph_path = dep_graph_path(tcx).unwrap();
70+
let dep_graph_path = dep_graph_path(tcx.sess);
5271
let dep_graph_data = match load_data(tcx.sess, &dep_graph_path) {
5372
Some(p) => p,
5473
None => return // no file
5574
};
5675

57-
let work_products_path = tcx_work_products_path(tcx).unwrap();
76+
let work_products_path = work_products_path(tcx.sess);
5877
let work_products_data = match load_data(tcx.sess, &work_products_path) {
5978
Some(p) => p,
6079
None => return // no file
@@ -250,7 +269,7 @@ fn reconcile_work_products<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
250269
.saved_files
251270
.iter()
252271
.all(|&(_, ref file_name)| {
253-
let path = in_incr_comp_dir(tcx.sess, &file_name).unwrap();
272+
let path = in_incr_comp_dir_sess(tcx.sess, &file_name);
254273
path.exists()
255274
});
256275
if all_files_exist {
@@ -268,7 +287,7 @@ fn delete_dirty_work_product(tcx: TyCtxt,
268287
swp: SerializedWorkProduct) {
269288
debug!("delete_dirty_work_product({:?})", swp);
270289
for &(_, ref file_name) in &swp.work_product.saved_files {
271-
let path = in_incr_comp_dir(tcx.sess, file_name).unwrap();
290+
let path = in_incr_comp_dir_sess(tcx.sess, file_name);
272291
match fs::remove_file(&path) {
273292
Ok(()) => { }
274293
Err(err) => {

‎src/librustc_incremental/persist/mod.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,16 @@
1515
mod data;
1616
mod directory;
1717
mod dirty_clean;
18+
mod fs;
1819
mod hash;
1920
mod load;
2021
mod preds;
2122
mod save;
22-
mod util;
2323
mod work_product;
2424

25+
pub use self::fs::finalize_session_directory;
26+
pub use self::fs::in_incr_comp_dir;
2527
pub use self::load::load_dep_graph;
2628
pub use self::save::save_dep_graph;
2729
pub use self::save::save_work_products;
2830
pub use self::work_product::save_trans_partition;
29-
pub use self::util::in_incr_comp_dir;

‎src/librustc_incremental/persist/save.rs

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
use rbml::opaque::Encoder;
1212
use rustc::dep_graph::DepNode;
1313
use rustc::hir::def_id::DefId;
14-
use rustc::middle::cstore::LOCAL_CRATE;
14+
use rustc::hir::svh::Svh;
1515
use rustc::session::Session;
1616
use rustc::ty::TyCtxt;
1717
use rustc_data_structures::fnv::FnvHashMap;
@@ -20,14 +20,14 @@ use std::hash::{Hash, Hasher, SipHasher};
2020
use std::io::{self, Cursor, Write};
2121
use std::fs::{self, File};
2222
use std::path::PathBuf;
23-
2423
use super::data::*;
2524
use super::directory::*;
2625
use super::hash::*;
2726
use super::preds::*;
28-
use super::util::*;
27+
use super::fs::*;
2928

30-
pub fn save_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
29+
pub fn save_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
30+
svh: Svh) {
3131
debug!("save_dep_graph()");
3232
let _ignore = tcx.dep_graph.in_ignore();
3333
let sess = tcx.sess;
@@ -39,31 +39,31 @@ pub fn save_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
3939
let query = tcx.dep_graph.query();
4040
let preds = Predecessors::new(&query, &mut hcx);
4141
save_in(sess,
42-
dep_graph_path(tcx),
42+
dep_graph_path(sess),
4343
|e| encode_dep_graph(&preds, &mut builder, e));
4444
save_in(sess,
45-
metadata_hash_path(tcx, LOCAL_CRATE),
46-
|e| encode_metadata_hashes(tcx, &preds, &mut builder, e));
45+
metadata_hash_export_path(sess),
46+
|e| encode_metadata_hashes(tcx, svh, &preds, &mut builder, e));
4747
}
4848

49-
pub fn save_work_products(sess: &Session, local_crate_name: &str) {
49+
pub fn save_work_products(sess: &Session) {
50+
if sess.opts.incremental.is_none() {
51+
return;
52+
}
53+
5054
debug!("save_work_products()");
5155
let _ignore = sess.dep_graph.in_ignore();
52-
let path = sess_work_products_path(sess, local_crate_name);
56+
let path = work_products_path(sess);
5357
save_in(sess, path, |e| encode_work_products(sess, e));
5458
}
5559

56-
fn save_in<F>(sess: &Session, opt_path_buf: Option<PathBuf>, encode: F)
60+
fn save_in<F>(sess: &Session, path_buf: PathBuf, encode: F)
5761
where F: FnOnce(&mut Encoder) -> io::Result<()>
5862
{
59-
let path_buf = match opt_path_buf {
60-
Some(p) => p,
61-
None => return,
62-
};
63-
64-
// FIXME(#32754) lock file?
65-
6663
// delete the old dep-graph, if any
64+
// Note: It's important that we actually delete the old file and not just
65+
// truncate and overwrite it, since it might be a shared hard-link, the
66+
// underlying data of which we don't want to modify
6767
if path_buf.exists() {
6868
match fs::remove_file(&path_buf) {
6969
Ok(()) => {}
@@ -153,6 +153,7 @@ pub fn encode_dep_graph(preds: &Predecessors,
153153
}
154154

155155
pub fn encode_metadata_hashes(tcx: TyCtxt,
156+
svh: Svh,
156157
preds: &Predecessors,
157158
builder: &mut DefIdDirectoryBuilder,
158159
encoder: &mut Encoder)
@@ -218,6 +219,7 @@ pub fn encode_metadata_hashes(tcx: TyCtxt,
218219
}
219220

220221
// Encode everything.
222+
try!(svh.encode(encoder));
221223
try!(serialized_hashes.encode(encoder));
222224

223225
Ok(())

‎src/librustc_incremental/persist/util.rs

Lines changed: 0 additions & 95 deletions
This file was deleted.

‎src/librustc_incremental/persist/work_product.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
//! This module contains files for saving intermediate work-products.
1212
13-
use persist::util::*;
13+
use persist::fs::*;
1414
use rustc::dep_graph::{WorkProduct, WorkProductId};
1515
use rustc::session::Session;
1616
use rustc::session::config::OutputType;
@@ -35,7 +35,7 @@ pub fn save_trans_partition(sess: &Session,
3535
files.iter()
3636
.map(|&(kind, ref path)| {
3737
let file_name = format!("cgu-{}.{}", cgu_name, kind.extension());
38-
let path_in_incr_dir = in_incr_comp_dir(sess, &file_name).unwrap();
38+
let path_in_incr_dir = in_incr_comp_dir_sess(sess, &file_name);
3939
match link_or_copy(path, &path_in_incr_dir) {
4040
Ok(_) => Some((kind, file_name)),
4141
Err(err) => {

‎src/librustc_trans/back/write.rs

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
use back::lto;
1212
use back::link::{get_linker, remove};
13-
use rustc_incremental::save_trans_partition;
13+
use rustc_incremental::{save_trans_partition, in_incr_comp_dir};
1414
use session::config::{OutputFilenames, OutputTypes, Passes, SomePasses, AllPasses};
1515
use session::Session;
1616
use session::config::{self, OutputType};
@@ -328,8 +328,9 @@ struct CodegenContext<'a> {
328328
remark: Passes,
329329
// Worker thread number
330330
worker: usize,
331-
// Directory where incremental data is stored (if any)
332-
incremental: Option<PathBuf>,
331+
// The incremental compilation session directory, or None if we are not
332+
// compiling incrementally
333+
incr_comp_session_dir: Option<PathBuf>
333334
}
334335

335336
impl<'a> CodegenContext<'a> {
@@ -340,7 +341,7 @@ impl<'a> CodegenContext<'a> {
340341
plugin_passes: sess.plugin_llvm_passes.borrow().clone(),
341342
remark: sess.opts.cg.remark.clone(),
342343
worker: 0,
343-
incremental: sess.opts.incremental.clone(),
344+
incr_comp_session_dir: sess.incr_comp_session_dir_opt().map(|r| r.clone())
344345
}
345346
}
346347
}
@@ -962,17 +963,20 @@ fn execute_work_item(cgcx: &CodegenContext,
962963
work_item.output_names);
963964
}
964965
ModuleSource::Preexisting(wp) => {
965-
let incremental = cgcx.incremental.as_ref().unwrap();
966+
let incr_comp_session_dir = cgcx.incr_comp_session_dir
967+
.as_ref()
968+
.unwrap();
966969
let name = &work_item.mtrans.name;
967970
for (kind, saved_file) in wp.saved_files {
968971
let obj_out = work_item.output_names.temp_path(kind, Some(name));
969-
let source_file = incremental.join(&saved_file);
972+
let source_file = in_incr_comp_dir(&incr_comp_session_dir,
973+
&saved_file);
970974
debug!("copying pre-existing module `{}` from {:?} to {}",
971975
work_item.mtrans.name,
972976
source_file,
973977
obj_out.display());
974978
match link_or_copy(&source_file, &obj_out) {
975-
Ok(()) => { }
979+
Ok(_) => { }
976980
Err(err) => {
977981
cgcx.handler.err(&format!("unable to copy {} to {}: {}",
978982
source_file.display(),
@@ -1018,7 +1022,7 @@ fn run_work_multithreaded(sess: &Session,
10181022
let mut tx = Some(tx);
10191023
futures.push(rx);
10201024

1021-
let incremental = sess.opts.incremental.clone();
1025+
let incr_comp_session_dir = sess.incr_comp_session_dir_opt().map(|r| r.clone());
10221026

10231027
thread::Builder::new().name(format!("codegen-{}", i)).spawn(move || {
10241028
let diag_handler = Handler::with_emitter(true, false, box diag_emitter);
@@ -1031,7 +1035,7 @@ fn run_work_multithreaded(sess: &Session,
10311035
plugin_passes: plugin_passes,
10321036
remark: remark,
10331037
worker: i,
1034-
incremental: incremental,
1038+
incr_comp_session_dir: incr_comp_session_dir
10351039
};
10361040

10371041
loop {

0 commit comments

Comments
 (0)
Please sign in to comment.