1
Fork 0

Have Queries own the GlobalCtxt.

The construction of the GlobalCtxt is moved from a generator's stack to
the Queries struct.  Since the GlobalCtxt requires the HIR Forest and the
arenas to live longer, those are moved into Queries the same way.

The resulting handling of objects is more brittle, because consumers of
the Once objects need to be careful of their initialisation.
This commit is contained in:
Camille GILLOT 2019-11-26 22:51:02 +01:00
parent 58a9c73bbd
commit b99513be57
3 changed files with 57 additions and 54 deletions

View file

@ -22,7 +22,7 @@ use rustc_codegen_ssa::back::link::emit_metadata;
use rustc_codegen_utils::codegen_backend::CodegenBackend; use rustc_codegen_utils::codegen_backend::CodegenBackend;
use rustc_codegen_utils::link::filename_for_metadata; use rustc_codegen_utils::link::filename_for_metadata;
use rustc_data_structures::{box_region_allow_access, declare_box_region_type, parallel}; use rustc_data_structures::{box_region_allow_access, declare_box_region_type, parallel};
use rustc_data_structures::sync::{Lrc, ParallelIterator, par_iter}; use rustc_data_structures::sync::{Lrc, Once, ParallelIterator, par_iter};
use rustc_errors::PResult; use rustc_errors::PResult;
use rustc_incremental; use rustc_incremental;
use rustc_metadata::cstore; use rustc_metadata::cstore;
@ -740,44 +740,41 @@ pub fn default_provide_extern(providers: &mut ty::query::Providers<'_>) {
rustc_codegen_ssa::provide_extern(providers); rustc_codegen_ssa::provide_extern(providers);
} }
declare_box_region_type!( pub struct BoxedGlobalCtxt<'tcx>(&'tcx GlobalCtxt<'tcx>);
pub BoxedGlobalCtxt,
for('tcx),
(&'tcx GlobalCtxt<'tcx>) -> ((), ())
);
impl BoxedGlobalCtxt { impl<'gcx> BoxedGlobalCtxt<'gcx> {
pub fn enter<F, R>(&mut self, f: F) -> R pub fn enter<F, R>(&mut self, f: F) -> R
where where
F: for<'tcx> FnOnce(TyCtxt<'tcx>) -> R, F: for<'tcx> FnOnce(TyCtxt<'tcx>) -> R,
{ {
self.access(|gcx| ty::tls::enter_global(gcx, |tcx| f(tcx))) ty::tls::enter_global(self.0, |tcx| f(tcx))
}
pub fn print_stats(&self) {
self.0.queries.print_stats()
} }
} }
pub fn create_global_ctxt( pub fn create_global_ctxt<'gcx>(
compiler: &Compiler, compiler: &'gcx Compiler,
lint_store: Lrc<lint::LintStore>, lint_store: Lrc<lint::LintStore>,
mut hir_forest: hir::map::Forest, hir_forest: &'gcx hir::map::Forest,
mut resolver_outputs: ResolverOutputs, mut resolver_outputs: ResolverOutputs,
outputs: OutputFilenames, outputs: OutputFilenames,
crate_name: &str, crate_name: &str,
) -> BoxedGlobalCtxt { global_ctxt: &'gcx Once<GlobalCtxt<'gcx>>,
let sess = compiler.session().clone(); arenas: &'gcx Once<AllArenas>,
) -> BoxedGlobalCtxt<'gcx> {
let sess = &compiler.session();
let codegen_backend = compiler.codegen_backend().clone(); let codegen_backend = compiler.codegen_backend().clone();
let crate_name = crate_name.to_string();
let defs = mem::take(&mut resolver_outputs.definitions); let defs = mem::take(&mut resolver_outputs.definitions);
let override_queries = compiler.override_queries; let override_queries = compiler.override_queries;
let ((), result) = BoxedGlobalCtxt::new(static move || { let arenas = arenas.init_locking(|| AllArenas::new());
let sess = &*sess;
let global_ctxt: Option<GlobalCtxt<'_>>;
let arenas = AllArenas::new();
// Construct the HIR map. // Construct the HIR map.
let hir_map = time(sess, "indexing HIR", || { let hir_map = time(sess, "indexing HIR", || {
hir::map::map_crate(sess, &*resolver_outputs.cstore, &mut hir_forest, defs) hir::map::map_crate(sess, &*resolver_outputs.cstore, &hir_forest, defs)
}); });
let query_result_on_disk_cache = time(sess, "load query result cache", || { let query_result_on_disk_cache = time(sess, "load query result cache", || {
@ -796,7 +793,7 @@ pub fn create_global_ctxt(
callback(sess, &mut local_providers, &mut extern_providers); callback(sess, &mut local_providers, &mut extern_providers);
} }
let gcx = TyCtxt::create_global_ctxt( let gcx = global_ctxt.init_locking(move || TyCtxt::create_global_ctxt(
sess, sess,
lint_store, lint_store,
local_providers, local_providers,
@ -807,26 +804,15 @@ pub fn create_global_ctxt(
query_result_on_disk_cache, query_result_on_disk_cache,
&crate_name, &crate_name,
&outputs &outputs
); ));
global_ctxt = Some(gcx); ty::tls::enter_global(&gcx, |tcx| {
let gcx = global_ctxt.as_ref().unwrap();
ty::tls::enter_global(gcx, |tcx| {
// Do some initialization of the DepGraph that can only be done with the // Do some initialization of the DepGraph that can only be done with the
// tcx available. // tcx available.
time(tcx.sess, "dep graph tcx init", || rustc_incremental::dep_graph_tcx_init(tcx)); time(tcx.sess, "dep graph tcx init", || rustc_incremental::dep_graph_tcx_init(tcx));
}); });
yield BoxedGlobalCtxt::initial_yield(()); BoxedGlobalCtxt(gcx)
box_region_allow_access!(for('tcx), (&'tcx GlobalCtxt<'tcx>), (gcx));
if sess.opts.debugging_opts.query_stats {
gcx.queries.print_stats();
}
});
result
} }
/// Runs the resolution, type-checking, region checking and other /// Runs the resolution, type-checking, region checking and other

View file

@ -2,7 +2,7 @@ use crate::interface::{Compiler, Result};
use crate::passes::{self, BoxedResolver, BoxedGlobalCtxt}; use crate::passes::{self, BoxedResolver, BoxedGlobalCtxt};
use rustc_incremental::DepGraphFuture; use rustc_incremental::DepGraphFuture;
use rustc_data_structures::sync::Lrc; use rustc_data_structures::sync::{Lrc, Once};
use rustc_codegen_utils::codegen_backend::CodegenBackend; use rustc_codegen_utils::codegen_backend::CodegenBackend;
use rustc::session::config::{OutputFilenames, OutputType}; use rustc::session::config::{OutputFilenames, OutputType};
use rustc::util::common::{time, ErrorReported}; use rustc::util::common::{time, ErrorReported};
@ -12,7 +12,7 @@ use rustc::session::Session;
use rustc::lint::LintStore; use rustc::lint::LintStore;
use rustc::hir::def_id::LOCAL_CRATE; use rustc::hir::def_id::LOCAL_CRATE;
use rustc::ty::steal::Steal; use rustc::ty::steal::Steal;
use rustc::ty::ResolverOutputs; use rustc::ty::{AllArenas, ResolverOutputs, GlobalCtxt};
use rustc::dep_graph::DepGraph; use rustc::dep_graph::DepGraph;
use std::cell::{Ref, RefMut, RefCell}; use std::cell::{Ref, RefMut, RefCell};
use std::rc::Rc; use std::rc::Rc;
@ -70,6 +70,9 @@ impl<T> Default for Query<T> {
pub struct Queries<'comp> { pub struct Queries<'comp> {
compiler: &'comp Compiler, compiler: &'comp Compiler,
gcx: Once<GlobalCtxt<'comp>>,
arenas: Once<AllArenas>,
forest: Once<hir::map::Forest>,
dep_graph_future: Query<Option<DepGraphFuture>>, dep_graph_future: Query<Option<DepGraphFuture>>,
parse: Query<ast::Crate>, parse: Query<ast::Crate>,
@ -77,9 +80,9 @@ pub struct Queries<'comp> {
register_plugins: Query<(ast::Crate, Lrc<LintStore>)>, register_plugins: Query<(ast::Crate, Lrc<LintStore>)>,
expansion: Query<(ast::Crate, Steal<Rc<RefCell<BoxedResolver>>>, Lrc<LintStore>)>, expansion: Query<(ast::Crate, Steal<Rc<RefCell<BoxedResolver>>>, Lrc<LintStore>)>,
dep_graph: Query<DepGraph>, dep_graph: Query<DepGraph>,
lower_to_hir: Query<(Steal<hir::map::Forest>, Steal<ResolverOutputs>)>, lower_to_hir: Query<(&'comp hir::map::Forest, Steal<ResolverOutputs>)>,
prepare_outputs: Query<OutputFilenames>, prepare_outputs: Query<OutputFilenames>,
global_ctxt: Query<BoxedGlobalCtxt>, global_ctxt: Query<BoxedGlobalCtxt<'comp>>,
ongoing_codegen: Query<Box<dyn Any>>, ongoing_codegen: Query<Box<dyn Any>>,
} }
@ -87,6 +90,9 @@ impl<'comp> Queries<'comp> {
pub fn new(compiler: &'comp Compiler) -> Queries<'comp> { pub fn new(compiler: &'comp Compiler) -> Queries<'comp> {
Queries { Queries {
compiler, compiler,
gcx: Once::new(),
arenas: Once::new(),
forest: Once::new(),
dep_graph_future: Default::default(), dep_graph_future: Default::default(),
parse: Default::default(), parse: Default::default(),
crate_name: Default::default(), crate_name: Default::default(),
@ -209,15 +215,15 @@ impl<'comp> Queries<'comp> {
} }
pub fn lower_to_hir( pub fn lower_to_hir(
&self, &'comp self,
) -> Result<&Query<(Steal<hir::map::Forest>, Steal<ResolverOutputs>)>> { ) -> Result<&Query<(&'comp hir::map::Forest, Steal<ResolverOutputs>)>> {
self.lower_to_hir.compute(|| { self.lower_to_hir.compute(|| {
let expansion_result = self.expansion()?; let expansion_result = self.expansion()?;
let peeked = expansion_result.peek(); let peeked = expansion_result.peek();
let krate = &peeked.0; let krate = &peeked.0;
let resolver = peeked.1.steal(); let resolver = peeked.1.steal();
let lint_store = &peeked.2; let lint_store = &peeked.2;
let hir = Steal::new(resolver.borrow_mut().access(|resolver| { let hir = resolver.borrow_mut().access(|resolver| {
passes::lower_to_hir( passes::lower_to_hir(
self.session(), self.session(),
lint_store, lint_store,
@ -225,7 +231,8 @@ impl<'comp> Queries<'comp> {
&*self.dep_graph()?.peek(), &*self.dep_graph()?.peek(),
&krate &krate
) )
})?); })?;
let hir = self.forest.init_locking(|| hir);
Ok((hir, Steal::new(BoxedResolver::to_resolver_outputs(resolver)))) Ok((hir, Steal::new(BoxedResolver::to_resolver_outputs(resolver))))
}) })
} }
@ -242,25 +249,27 @@ impl<'comp> Queries<'comp> {
}) })
} }
pub fn global_ctxt(&self) -> Result<&Query<BoxedGlobalCtxt>> { pub fn global_ctxt(&'comp self) -> Result<&Query<BoxedGlobalCtxt<'comp>>> {
self.global_ctxt.compute(|| { self.global_ctxt.compute(|| {
let crate_name = self.crate_name()?.peek().clone(); let crate_name = self.crate_name()?.peek().clone();
let outputs = self.prepare_outputs()?.peek().clone(); let outputs = self.prepare_outputs()?.peek().clone();
let lint_store = self.expansion()?.peek().2.clone(); let lint_store = self.expansion()?.peek().2.clone();
let hir = self.lower_to_hir()?; let hir = self.lower_to_hir()?.peek();
let hir = hir.peek(); let (ref hir_forest, ref resolver_outputs) = &*hir;
let (hir_forest, resolver_outputs) = &*hir;
Ok(passes::create_global_ctxt( Ok(passes::create_global_ctxt(
self.compiler, self.compiler,
lint_store, lint_store,
hir_forest.steal(), hir_forest,
resolver_outputs.steal(), resolver_outputs.steal(),
outputs, outputs,
&crate_name)) &crate_name,
&self.gcx,
&self.arenas,
))
}) })
} }
pub fn ongoing_codegen(&self) -> Result<&Query<Box<dyn Any>>> { pub fn ongoing_codegen(&'comp self) -> Result<&Query<Box<dyn Any>>> {
self.ongoing_codegen.compute(|| { self.ongoing_codegen.compute(|| {
let outputs = self.prepare_outputs()?; let outputs = self.prepare_outputs()?;
self.global_ctxt()?.peek_mut().enter(|tcx| { self.global_ctxt()?.peek_mut().enter(|tcx| {
@ -278,7 +287,7 @@ impl<'comp> Queries<'comp> {
}) })
} }
pub fn linker(&self) -> Result<Linker> { pub fn linker(&'comp self) -> Result<Linker> {
let dep_graph = self.dep_graph()?; let dep_graph = self.dep_graph()?;
let prepare_outputs = self.prepare_outputs()?; let prepare_outputs = self.prepare_outputs()?;
let ongoing_codegen = self.ongoing_codegen()?; let ongoing_codegen = self.ongoing_codegen()?;
@ -317,10 +326,18 @@ impl Linker {
impl Compiler { impl Compiler {
pub fn enter<F, T>(&self, f: F) -> T pub fn enter<F, T>(&self, f: F) -> T
where F: FnOnce(&Queries<'_>) -> T where F: for<'tcx> FnOnce(&'tcx Queries<'tcx>) -> T
{ {
let queries = Queries::new(&self); let queries = Queries::new(&self);
f(&queries) let ret = f(&queries);
if self.session().opts.debugging_opts.query_stats {
if let Ok(gcx) = queries.global_ctxt() {
gcx.peek().print_stats();
}
}
ret
} }
// This method is different to all the other methods in `Compiler` because // This method is different to all the other methods in `Compiler` because

View file

@ -88,7 +88,7 @@ pub fn run(options: Options) -> i32 {
let tests = interface::run_compiler(config, |compiler| compiler.enter(|queries| { let tests = interface::run_compiler(config, |compiler| compiler.enter(|queries| {
let lower_to_hir = queries.lower_to_hir()?; let lower_to_hir = queries.lower_to_hir()?;
let mut opts = scrape_test_config(lower_to_hir.peek().0.borrow().krate()); let mut opts = scrape_test_config(lower_to_hir.peek().0.krate());
opts.display_warnings |= options.display_warnings; opts.display_warnings |= options.display_warnings;
let enable_per_target_ignores = options.enable_per_target_ignores; let enable_per_target_ignores = options.enable_per_target_ignores;
let mut collector = Collector::new( let mut collector = Collector::new(