Don't use a thread to load the dep graph
This commit is contained in:
parent
13e6f24b9a
commit
ba8d53dc8f
5 changed files with 68 additions and 118 deletions
|
@ -28,8 +28,8 @@ pub use persist::load_query_result_cache;
|
||||||
pub use persist::prepare_session_directory;
|
pub use persist::prepare_session_directory;
|
||||||
pub use persist::save_dep_graph;
|
pub use persist::save_dep_graph;
|
||||||
pub use persist::save_work_product_index;
|
pub use persist::save_work_product_index;
|
||||||
|
pub use persist::setup_dep_graph;
|
||||||
pub use persist::LoadResult;
|
pub use persist::LoadResult;
|
||||||
pub use persist::{build_dep_graph, load_dep_graph, DepGraphFuture};
|
|
||||||
|
|
||||||
use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
|
use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
|
||||||
use rustc_fluent_macro::fluent_messages;
|
use rustc_fluent_macro::fluent_messages;
|
||||||
|
|
|
@ -3,17 +3,19 @@
|
||||||
use crate::errors;
|
use crate::errors;
|
||||||
use rustc_data_structures::memmap::Mmap;
|
use rustc_data_structures::memmap::Mmap;
|
||||||
use rustc_data_structures::unord::UnordMap;
|
use rustc_data_structures::unord::UnordMap;
|
||||||
use rustc_middle::dep_graph::{DepsType, SerializedDepGraph, WorkProductMap};
|
use rustc_middle::dep_graph::{DepGraph, DepsType, SerializedDepGraph, WorkProductMap};
|
||||||
use rustc_middle::query::on_disk_cache::OnDiskCache;
|
use rustc_middle::query::on_disk_cache::OnDiskCache;
|
||||||
use rustc_serialize::opaque::MemDecoder;
|
use rustc_serialize::opaque::MemDecoder;
|
||||||
use rustc_serialize::Decodable;
|
use rustc_serialize::Decodable;
|
||||||
use rustc_session::config::IncrementalStateAssertion;
|
use rustc_session::config::IncrementalStateAssertion;
|
||||||
use rustc_session::Session;
|
use rustc_session::{Session, StableCrateId};
|
||||||
|
use rustc_span::{ErrorGuaranteed, Symbol};
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
use super::data::*;
|
use super::data::*;
|
||||||
use super::file_format;
|
use super::file_format;
|
||||||
use super::fs::*;
|
use super::fs::*;
|
||||||
|
use super::save::build_dep_graph;
|
||||||
use super::work_product;
|
use super::work_product;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -72,21 +74,12 @@ impl<T: Default> LoadResult<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_data(path: &Path, sess: &Session) -> LoadResult<(Mmap, usize)> {
|
fn load_data(path: &Path, sess: &Session) -> LoadResult<(Mmap, usize)> {
|
||||||
load_data_no_sess(
|
match file_format::read_file(
|
||||||
path,
|
path,
|
||||||
sess.opts.unstable_opts.incremental_info,
|
sess.opts.unstable_opts.incremental_info,
|
||||||
sess.is_nightly_build(),
|
sess.is_nightly_build(),
|
||||||
sess.cfg_version,
|
sess.cfg_version,
|
||||||
)
|
) {
|
||||||
}
|
|
||||||
|
|
||||||
fn load_data_no_sess(
|
|
||||||
path: &Path,
|
|
||||||
report_incremental_info: bool,
|
|
||||||
is_nightly_build: bool,
|
|
||||||
cfg_version: &'static str,
|
|
||||||
) -> LoadResult<(Mmap, usize)> {
|
|
||||||
match file_format::read_file(path, report_incremental_info, is_nightly_build, cfg_version) {
|
|
||||||
Ok(Some(data_and_pos)) => LoadResult::Ok { data: data_and_pos },
|
Ok(Some(data_and_pos)) => LoadResult::Ok { data: data_and_pos },
|
||||||
Ok(None) => {
|
Ok(None) => {
|
||||||
// The file either didn't exist or was produced by an incompatible
|
// The file either didn't exist or was produced by an incompatible
|
||||||
|
@ -102,39 +95,12 @@ fn delete_dirty_work_product(sess: &Session, swp: SerializedWorkProduct) {
|
||||||
work_product::delete_workproduct_files(sess, &swp.work_product);
|
work_product::delete_workproduct_files(sess, &swp.work_product);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Either a result that has already be computed or a
|
fn load_dep_graph(sess: &Session) -> LoadResult<(SerializedDepGraph, WorkProductMap)> {
|
||||||
/// handle that will let us wait until it is computed
|
|
||||||
/// by a background thread.
|
|
||||||
pub enum MaybeAsync<T> {
|
|
||||||
Sync(T),
|
|
||||||
Async(std::thread::JoinHandle<T>),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> MaybeAsync<LoadResult<T>> {
|
|
||||||
/// Accesses the data returned in [`LoadResult::Ok`] in an asynchronous way if possible.
|
|
||||||
pub fn open(self) -> LoadResult<T> {
|
|
||||||
match self {
|
|
||||||
MaybeAsync::Sync(result) => result,
|
|
||||||
MaybeAsync::Async(handle) => {
|
|
||||||
handle.join().unwrap_or_else(|e| LoadResult::DecodeIncrCache(e))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// An asynchronous type for computing the dependency graph.
|
|
||||||
pub type DepGraphFuture = MaybeAsync<LoadResult<(SerializedDepGraph, WorkProductMap)>>;
|
|
||||||
|
|
||||||
/// Launch a thread and load the dependency graph in the background.
|
|
||||||
pub fn load_dep_graph(sess: &Session) -> DepGraphFuture {
|
|
||||||
// Since `sess` isn't `Sync`, we perform all accesses to `sess`
|
|
||||||
// before we fire the background thread.
|
|
||||||
|
|
||||||
let prof = sess.prof.clone();
|
let prof = sess.prof.clone();
|
||||||
|
|
||||||
if sess.opts.incremental.is_none() {
|
if sess.opts.incremental.is_none() {
|
||||||
// No incremental compilation.
|
// No incremental compilation.
|
||||||
return MaybeAsync::Sync(LoadResult::Ok { data: Default::default() });
|
return LoadResult::Ok { data: Default::default() };
|
||||||
}
|
}
|
||||||
|
|
||||||
let _timer = sess.prof.generic_activity("incr_comp_prepare_load_dep_graph");
|
let _timer = sess.prof.generic_activity("incr_comp_prepare_load_dep_graph");
|
||||||
|
@ -142,7 +108,6 @@ pub fn load_dep_graph(sess: &Session) -> DepGraphFuture {
|
||||||
// Calling `sess.incr_comp_session_dir()` will panic if `sess.opts.incremental.is_none()`.
|
// Calling `sess.incr_comp_session_dir()` will panic if `sess.opts.incremental.is_none()`.
|
||||||
// Fortunately, we just checked that this isn't the case.
|
// Fortunately, we just checked that this isn't the case.
|
||||||
let path = dep_graph_path(&sess);
|
let path = dep_graph_path(&sess);
|
||||||
let report_incremental_info = sess.opts.unstable_opts.incremental_info;
|
|
||||||
let expected_hash = sess.opts.dep_tracking_hash(false);
|
let expected_hash = sess.opts.dep_tracking_hash(false);
|
||||||
|
|
||||||
let mut prev_work_products = UnordMap::default();
|
let mut prev_work_products = UnordMap::default();
|
||||||
|
@ -180,13 +145,9 @@ pub fn load_dep_graph(sess: &Session) -> DepGraphFuture {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let is_nightly_build = sess.is_nightly_build();
|
|
||||||
let cfg_version = sess.cfg_version;
|
|
||||||
|
|
||||||
MaybeAsync::Async(std::thread::spawn(move || {
|
|
||||||
let _prof_timer = prof.generic_activity("incr_comp_load_dep_graph");
|
let _prof_timer = prof.generic_activity("incr_comp_load_dep_graph");
|
||||||
|
|
||||||
match load_data_no_sess(&path, report_incremental_info, is_nightly_build, cfg_version) {
|
match load_data(&path, sess) {
|
||||||
LoadResult::DataOutOfDate => LoadResult::DataOutOfDate,
|
LoadResult::DataOutOfDate => LoadResult::DataOutOfDate,
|
||||||
LoadResult::LoadDepGraph(path, err) => LoadResult::LoadDepGraph(path, err),
|
LoadResult::LoadDepGraph(path, err) => LoadResult::LoadDepGraph(path, err),
|
||||||
LoadResult::DecodeIncrCache(err) => LoadResult::DecodeIncrCache(err),
|
LoadResult::DecodeIncrCache(err) => LoadResult::DecodeIncrCache(err),
|
||||||
|
@ -195,7 +156,7 @@ pub fn load_dep_graph(sess: &Session) -> DepGraphFuture {
|
||||||
let prev_commandline_args_hash = u64::decode(&mut decoder);
|
let prev_commandline_args_hash = u64::decode(&mut decoder);
|
||||||
|
|
||||||
if prev_commandline_args_hash != expected_hash {
|
if prev_commandline_args_hash != expected_hash {
|
||||||
if report_incremental_info {
|
if sess.opts.unstable_opts.incremental_info {
|
||||||
eprintln!(
|
eprintln!(
|
||||||
"[incremental] completely ignoring cache because of \
|
"[incremental] completely ignoring cache because of \
|
||||||
differing commandline arguments"
|
differing commandline arguments"
|
||||||
|
@ -213,7 +174,6 @@ pub fn load_dep_graph(sess: &Session) -> DepGraphFuture {
|
||||||
LoadResult::Ok { data: (dep_graph, prev_work_products) }
|
LoadResult::Ok { data: (dep_graph, prev_work_products) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Attempts to load the query result cache from disk
|
/// Attempts to load the query result cache from disk
|
||||||
|
@ -235,3 +195,35 @@ pub fn load_query_result_cache(sess: &Session) -> Option<OnDiskCache<'_>> {
|
||||||
_ => Some(OnDiskCache::new_empty(sess.source_map())),
|
_ => Some(OnDiskCache::new_empty(sess.source_map())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Setups the dependency graph by loading an existing graph from disk and set up streaming of a
|
||||||
|
/// new graph to an incremental session directory.
|
||||||
|
pub fn setup_dep_graph(
|
||||||
|
sess: &Session,
|
||||||
|
crate_name: Symbol,
|
||||||
|
stable_crate_id: StableCrateId,
|
||||||
|
) -> Result<DepGraph, ErrorGuaranteed> {
|
||||||
|
// `load_dep_graph` can only be called after `prepare_session_directory`.
|
||||||
|
prepare_session_directory(sess, crate_name, stable_crate_id)?;
|
||||||
|
|
||||||
|
let res = sess.opts.build_dep_graph().then(|| load_dep_graph(sess));
|
||||||
|
|
||||||
|
if sess.opts.incremental.is_some() {
|
||||||
|
sess.time("incr_comp_garbage_collect_session_directories", || {
|
||||||
|
if let Err(e) = garbage_collect_session_directories(sess) {
|
||||||
|
warn!(
|
||||||
|
"Error while trying to garbage collect incremental \
|
||||||
|
compilation cache directory: {}",
|
||||||
|
e
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(res
|
||||||
|
.and_then(|result| {
|
||||||
|
let (prev_graph, prev_work_products) = result.open(sess);
|
||||||
|
build_dep_graph(sess, prev_graph, prev_work_products)
|
||||||
|
})
|
||||||
|
.unwrap_or_else(DepGraph::new_disabled))
|
||||||
|
}
|
||||||
|
|
|
@ -16,9 +16,8 @@ pub use fs::in_incr_comp_dir;
|
||||||
pub use fs::in_incr_comp_dir_sess;
|
pub use fs::in_incr_comp_dir_sess;
|
||||||
pub use fs::prepare_session_directory;
|
pub use fs::prepare_session_directory;
|
||||||
pub use load::load_query_result_cache;
|
pub use load::load_query_result_cache;
|
||||||
|
pub use load::setup_dep_graph;
|
||||||
pub use load::LoadResult;
|
pub use load::LoadResult;
|
||||||
pub use load::{load_dep_graph, DepGraphFuture};
|
|
||||||
pub use save::build_dep_graph;
|
|
||||||
pub use save::save_dep_graph;
|
pub use save::save_dep_graph;
|
||||||
pub use save::save_work_product_index;
|
pub use save::save_work_product_index;
|
||||||
pub use work_product::copy_cgu_workproduct_to_incr_comp_cache_dir;
|
pub use work_product::copy_cgu_workproduct_to_incr_comp_cache_dir;
|
||||||
|
|
|
@ -147,7 +147,7 @@ fn encode_query_cache(tcx: TyCtxt<'_>, encoder: FileEncoder) -> FileEncodeResult
|
||||||
/// execution, the new dependency information is not kept in memory but directly
|
/// execution, the new dependency information is not kept in memory but directly
|
||||||
/// output to this file. `save_dep_graph` then finalizes the staging dep-graph
|
/// output to this file. `save_dep_graph` then finalizes the staging dep-graph
|
||||||
/// and moves it to the permanent dep-graph path
|
/// and moves it to the permanent dep-graph path
|
||||||
pub fn build_dep_graph(
|
pub(crate) fn build_dep_graph(
|
||||||
sess: &Session,
|
sess: &Session,
|
||||||
prev_graph: SerializedDepGraph,
|
prev_graph: SerializedDepGraph,
|
||||||
prev_work_products: WorkProductMap,
|
prev_work_products: WorkProductMap,
|
||||||
|
|
|
@ -10,7 +10,7 @@ use rustc_data_structures::svh::Svh;
|
||||||
use rustc_data_structures::sync::{AppendOnlyIndexVec, FreezeLock, Lrc, OnceLock, WorkerLocal};
|
use rustc_data_structures::sync::{AppendOnlyIndexVec, FreezeLock, Lrc, OnceLock, WorkerLocal};
|
||||||
use rustc_hir::def_id::{StableCrateId, CRATE_DEF_ID, LOCAL_CRATE};
|
use rustc_hir::def_id::{StableCrateId, CRATE_DEF_ID, LOCAL_CRATE};
|
||||||
use rustc_hir::definitions::Definitions;
|
use rustc_hir::definitions::Definitions;
|
||||||
use rustc_incremental::DepGraphFuture;
|
use rustc_incremental::setup_dep_graph;
|
||||||
use rustc_metadata::creader::CStore;
|
use rustc_metadata::creader::CStore;
|
||||||
use rustc_middle::arena::Arena;
|
use rustc_middle::arena::Arena;
|
||||||
use rustc_middle::dep_graph::DepGraph;
|
use rustc_middle::dep_graph::DepGraph;
|
||||||
|
@ -19,7 +19,6 @@ use rustc_session::config::{self, CrateType, OutputFilenames, OutputType};
|
||||||
use rustc_session::cstore::Untracked;
|
use rustc_session::cstore::Untracked;
|
||||||
use rustc_session::{output::find_crate_name, Session};
|
use rustc_session::{output::find_crate_name, Session};
|
||||||
use rustc_span::symbol::sym;
|
use rustc_span::symbol::sym;
|
||||||
use rustc_span::Symbol;
|
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use std::cell::{RefCell, RefMut};
|
use std::cell::{RefCell, RefMut};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
@ -132,43 +131,6 @@ impl<'tcx> Queries<'tcx> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dep_graph_future(
|
|
||||||
&self,
|
|
||||||
crate_name: Symbol,
|
|
||||||
stable_crate_id: StableCrateId,
|
|
||||||
) -> Result<Option<DepGraphFuture>> {
|
|
||||||
let sess = self.session();
|
|
||||||
|
|
||||||
// `load_dep_graph` can only be called after `prepare_session_directory`.
|
|
||||||
rustc_incremental::prepare_session_directory(sess, crate_name, stable_crate_id)?;
|
|
||||||
let res = sess.opts.build_dep_graph().then(|| rustc_incremental::load_dep_graph(sess));
|
|
||||||
|
|
||||||
if sess.opts.incremental.is_some() {
|
|
||||||
sess.time("incr_comp_garbage_collect_session_directories", || {
|
|
||||||
if let Err(e) = rustc_incremental::garbage_collect_session_directories(sess) {
|
|
||||||
warn!(
|
|
||||||
"Error while trying to garbage collect incremental \
|
|
||||||
compilation cache directory: {}",
|
|
||||||
e
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(res)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn dep_graph(&self, dep_graph_future: Option<DepGraphFuture>) -> DepGraph {
|
|
||||||
dep_graph_future
|
|
||||||
.and_then(|future| {
|
|
||||||
let sess = self.session();
|
|
||||||
let (prev_graph, prev_work_products) =
|
|
||||||
sess.time("blocked_on_dep_graph_loading", || future.open().open(sess));
|
|
||||||
rustc_incremental::build_dep_graph(sess, prev_graph, prev_work_products)
|
|
||||||
})
|
|
||||||
.unwrap_or_else(DepGraph::new_disabled)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn global_ctxt(&'tcx self) -> Result<QueryResult<'_, &'tcx GlobalCtxt<'tcx>>> {
|
pub fn global_ctxt(&'tcx self) -> Result<QueryResult<'_, &'tcx GlobalCtxt<'tcx>>> {
|
||||||
self.gcx.compute(|| {
|
self.gcx.compute(|| {
|
||||||
let sess = self.session();
|
let sess = self.session();
|
||||||
|
@ -184,10 +146,7 @@ impl<'tcx> Queries<'tcx> {
|
||||||
sess.opts.cg.metadata.clone(),
|
sess.opts.cg.metadata.clone(),
|
||||||
sess.cfg_version,
|
sess.cfg_version,
|
||||||
);
|
);
|
||||||
|
let dep_graph = setup_dep_graph(sess, crate_name, stable_crate_id)?;
|
||||||
// Compute the dependency graph (in the background). We want to do this as early as
|
|
||||||
// possible, to give the DepGraph maximum time to load before `dep_graph` is called.
|
|
||||||
let dep_graph_future = self.dep_graph_future(crate_name, stable_crate_id)?;
|
|
||||||
|
|
||||||
let lint_store = Lrc::new(passes::create_lint_store(
|
let lint_store = Lrc::new(passes::create_lint_store(
|
||||||
sess,
|
sess,
|
||||||
|
@ -210,7 +169,7 @@ impl<'tcx> Queries<'tcx> {
|
||||||
crate_types,
|
crate_types,
|
||||||
stable_crate_id,
|
stable_crate_id,
|
||||||
lint_store,
|
lint_store,
|
||||||
self.dep_graph(dep_graph_future),
|
dep_graph,
|
||||||
untracked,
|
untracked,
|
||||||
&self.gcx_cell,
|
&self.gcx_cell,
|
||||||
&self.arena,
|
&self.arena,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue