提交 266ede1b 编写于 作者: C Camille GILLOT

Isolate compiler queries inside the Queries type.

上级 412f43ac
......@@ -283,120 +283,124 @@ pub fn run_compiler(
return sess.compile_status();
}
compiler.parse()?;
if let Some(ppm) = &sess.opts.pretty {
if ppm.needs_ast_map() {
compiler.global_ctxt()?.peek_mut().enter(|tcx| {
let expanded_crate = compiler.expansion()?.take().0;
pretty::print_after_hir_lowering(
tcx,
compiler.input(),
&expanded_crate,
compiler.enter(|queries| {
queries.parse()?;
if let Some(ppm) = &sess.opts.pretty {
if ppm.needs_ast_map() {
queries.global_ctxt()?.peek_mut().enter(|tcx| {
let expanded_crate = queries.expansion()?.take().0;
pretty::print_after_hir_lowering(
tcx,
compiler.input(),
&expanded_crate,
*ppm,
compiler.output_file().as_ref().map(|p| &**p),
);
Ok(())
})?;
} else {
let krate = queries.parse()?.take();
pretty::print_after_parsing(
sess,
&compiler.input(),
&krate,
*ppm,
compiler.output_file().as_ref().map(|p| &**p),
);
Ok(())
})?;
} else {
let krate = compiler.parse()?.take();
pretty::print_after_parsing(
sess,
&compiler.input(),
&krate,
*ppm,
compiler.output_file().as_ref().map(|p| &**p),
);
}
return sess.compile_status();
}
return sess.compile_status();
}
if callbacks.after_parsing(compiler) == Compilation::Stop {
return sess.compile_status();
}
if callbacks.after_parsing(compiler) == Compilation::Stop {
return sess.compile_status();
}
if sess.opts.debugging_opts.parse_only ||
sess.opts.debugging_opts.show_span.is_some() ||
sess.opts.debugging_opts.ast_json_noexpand {
return sess.compile_status();
}
if sess.opts.debugging_opts.parse_only ||
sess.opts.debugging_opts.show_span.is_some() ||
sess.opts.debugging_opts.ast_json_noexpand {
return sess.compile_status();
}
{
let (_, lint_store) = &*queries.register_plugins()?.peek();
{
let (_, lint_store) = &*compiler.register_plugins()?.peek();
// Lint plugins are registered; now we can process command line flags.
if sess.opts.describe_lints {
describe_lints(&sess, &lint_store, true);
return sess.compile_status();
}
}
// Lint plugins are registered; now we can process command line flags.
if sess.opts.describe_lints {
describe_lints(&sess, &lint_store, true);
queries.expansion()?;
if callbacks.after_expansion(compiler) == Compilation::Stop {
return sess.compile_status();
}
}
compiler.expansion()?;
if callbacks.after_expansion(compiler) == Compilation::Stop {
return sess.compile_status();
}
queries.prepare_outputs()?;
if sess.opts.output_types.contains_key(&OutputType::DepInfo)
&& sess.opts.output_types.len() == 1
{
return sess.compile_status();
}
compiler.prepare_outputs()?;
queries.global_ctxt()?;
if sess.opts.output_types.contains_key(&OutputType::DepInfo)
&& sess.opts.output_types.len() == 1
{
return sess.compile_status();
}
if sess.opts.debugging_opts.no_analysis ||
sess.opts.debugging_opts.ast_json {
return sess.compile_status();
}
compiler.global_ctxt()?;
if sess.opts.debugging_opts.save_analysis {
let expanded_crate = &queries.expansion()?.peek().0;
let crate_name = queries.crate_name()?.peek().clone();
queries.global_ctxt()?.peek_mut().enter(|tcx| {
let result = tcx.analysis(LOCAL_CRATE);
time(sess, "save analysis", || {
save::process_crate(
tcx,
&expanded_crate,
&crate_name,
&compiler.input(),
None,
DumpHandler::new(compiler.output_dir().as_ref().map(|p| &**p), &crate_name)
)
});
if sess.opts.debugging_opts.no_analysis ||
sess.opts.debugging_opts.ast_json {
return sess.compile_status();
}
result
// AST will be dropped *after* the `after_analysis` callback
// (needed by the RLS)
})?;
} else {
// Drop AST after creating GlobalCtxt to free memory
mem::drop(queries.expansion()?.take());
}
if sess.opts.debugging_opts.save_analysis {
let expanded_crate = &compiler.expansion()?.peek().0;
let crate_name = compiler.crate_name()?.peek().clone();
compiler.global_ctxt()?.peek_mut().enter(|tcx| {
let result = tcx.analysis(LOCAL_CRATE);
time(sess, "save analysis", || {
save::process_crate(
tcx,
&expanded_crate,
&crate_name,
&compiler.input(),
None,
DumpHandler::new(compiler.output_dir().as_ref().map(|p| &**p), &crate_name)
)
});
result
// AST will be dropped *after* the `after_analysis` callback
// (needed by the RLS)
})?;
} else {
// Drop AST after creating GlobalCtxt to free memory
mem::drop(compiler.expansion()?.take());
}
queries.global_ctxt()?.peek_mut().enter(|tcx| tcx.analysis(LOCAL_CRATE))?;
compiler.global_ctxt()?.peek_mut().enter(|tcx| tcx.analysis(LOCAL_CRATE))?;
if callbacks.after_analysis(compiler) == Compilation::Stop {
return sess.compile_status();
}
if callbacks.after_analysis(compiler) == Compilation::Stop {
return sess.compile_status();
}
if sess.opts.debugging_opts.save_analysis {
mem::drop(queries.expansion()?.take());
}
if sess.opts.debugging_opts.save_analysis {
mem::drop(compiler.expansion()?.take());
}
queries.ongoing_codegen()?;
compiler.ongoing_codegen()?;
// Drop GlobalCtxt after starting codegen to free memory
mem::drop(queries.global_ctxt()?.take());
// Drop GlobalCtxt after starting codegen to free memory
mem::drop(compiler.global_ctxt()?.take());
if sess.opts.debugging_opts.print_type_sizes {
sess.code_stats.print_type_sizes();
}
if sess.opts.debugging_opts.print_type_sizes {
sess.code_stats.print_type_sizes();
}
queries.link()?;
compiler.link()?;
Ok(())
})?;
if sess.opts.debugging_opts.perf_stats {
sess.print_perf_stats();
......
use crate::queries::Queries;
use crate::util;
pub use crate::passes::BoxedResolver;
......@@ -36,7 +35,6 @@ pub struct Compiler {
pub(crate) input_path: Option<PathBuf>,
pub(crate) output_dir: Option<PathBuf>,
pub(crate) output_file: Option<PathBuf>,
pub(crate) queries: Queries,
pub(crate) crate_name: Option<String>,
pub(crate) register_lints: Option<Box<dyn Fn(&Session, &mut lint::LintStore) + Send + Sync>>,
pub(crate) override_queries:
......@@ -169,7 +167,6 @@ pub fn run_compiler_in_existing_thread_pool<R>(
input_path: config.input_path,
output_dir: config.output_dir,
output_file: config.output_file,
queries: Default::default(),
crate_name: config.crate_name,
register_lints: config.register_lints,
override_queries: config.override_queries,
......
......@@ -3,6 +3,7 @@
use rustc_incremental::DepGraphFuture;
use rustc_data_structures::sync::Lrc;
use rustc_codegen_utils::codegen_backend::CodegenBackend;
use rustc::session::config::{OutputFilenames, OutputType};
use rustc::util::common::{time, ErrorReported};
use rustc::hir;
......@@ -44,13 +45,6 @@ pub fn take(&self) -> T {
.unwrap()
}
/// Returns a stolen query result. Panics if there's already a result.
pub fn give(&self, value: T) {
let mut result = self.result.borrow_mut();
assert!(result.is_none(), "a result already exists");
*result = Some(Ok(value));
}
/// Borrows the query result using the RefCell. Panics if the result is stolen.
pub fn peek(&self) -> Ref<'_, T> {
Ref::map(self.result.borrow(), |r| {
......@@ -74,8 +68,9 @@ fn default() -> Self {
}
}
#[derive(Default)]
pub(crate) struct Queries {
pub struct Queries<'comp> {
compiler: &'comp Compiler,
dep_graph_future: Query<Option<DepGraphFuture>>,
parse: Query<ast::Crate>,
crate_name: Query<String>,
......@@ -89,9 +84,33 @@ pub(crate) struct Queries {
link: Query<()>,
}
impl Compiler {
impl<'comp> Queries<'comp> {
pub fn new(compiler: &'comp Compiler) -> Queries<'comp> {
Queries {
compiler,
dep_graph_future: Default::default(),
parse: Default::default(),
crate_name: Default::default(),
register_plugins: Default::default(),
expansion: Default::default(),
dep_graph: Default::default(),
lower_to_hir: Default::default(),
prepare_outputs: Default::default(),
global_ctxt: Default::default(),
ongoing_codegen: Default::default(),
link: Default::default(),
}
}
fn session(&self) -> &Lrc<Session> {
&self.compiler.sess
}
fn codegen_backend(&self) -> &Lrc<Box<dyn CodegenBackend>> {
&self.compiler.codegen_backend()
}
pub fn dep_graph_future(&self) -> Result<&Query<Option<DepGraphFuture>>> {
self.queries.dep_graph_future.compute(|| {
self.dep_graph_future.compute(|| {
Ok(if self.session().opts.build_dep_graph() {
Some(rustc_incremental::load_dep_graph(self.session()))
} else {
......@@ -101,8 +120,8 @@ pub fn dep_graph_future(&self) -> Result<&Query<Option<DepGraphFuture>>> {
}
pub fn parse(&self) -> Result<&Query<ast::Crate>> {
self.queries.parse.compute(|| {
passes::parse(self.session(), &self.input).map_err(
self.parse.compute(|| {
passes::parse(self.session(), &self.compiler.input).map_err(
|mut parse_error| {
parse_error.emit();
ErrorReported
......@@ -112,7 +131,7 @@ pub fn parse(&self) -> Result<&Query<ast::Crate>> {
}
pub fn register_plugins(&self) -> Result<&Query<(ast::Crate, Lrc<LintStore>)>> {
self.queries.register_plugins.compute(|| {
self.register_plugins.compute(|| {
let crate_name = self.crate_name()?.peek().clone();
let krate = self.parse()?.take();
......@@ -120,7 +139,7 @@ pub fn register_plugins(&self) -> Result<&Query<(ast::Crate, Lrc<LintStore>)>> {
let result = passes::register_plugins(
self.session(),
&*self.codegen_backend().metadata_loader(),
self.register_lints
self.compiler.register_lints
.as_ref()
.map(|p| &**p)
.unwrap_or_else(|| empty),
......@@ -140,8 +159,8 @@ pub fn register_plugins(&self) -> Result<&Query<(ast::Crate, Lrc<LintStore>)>> {
}
pub fn crate_name(&self) -> Result<&Query<String>> {
self.queries.crate_name.compute(|| {
Ok(match self.crate_name {
self.crate_name.compute(|| {
Ok(match self.compiler.crate_name {
Some(ref crate_name) => crate_name.clone(),
None => {
let parse_result = self.parse()?;
......@@ -149,7 +168,7 @@ pub fn crate_name(&self) -> Result<&Query<String>> {
rustc_codegen_utils::link::find_crate_name(
Some(self.session()),
&krate.attrs,
&self.input
&self.compiler.input
)
}
})
......@@ -159,11 +178,11 @@ pub fn crate_name(&self) -> Result<&Query<String>> {
pub fn expansion(
&self
) -> Result<&Query<(ast::Crate, Steal<Rc<RefCell<BoxedResolver>>>, Lrc<LintStore>)>> {
self.queries.expansion.compute(|| {
self.expansion.compute(|| {
let crate_name = self.crate_name()?.peek().clone();
let (krate, lint_store) = self.register_plugins()?.take();
passes::configure_and_expand(
self.sess.clone(),
self.session().clone(),
lint_store.clone(),
self.codegen_backend().metadata_loader(),
krate,
......@@ -175,7 +194,7 @@ pub fn expansion(
}
pub fn dep_graph(&self) -> Result<&Query<DepGraph>> {
self.queries.dep_graph.compute(|| {
self.dep_graph.compute(|| {
Ok(match self.dep_graph_future()?.take() {
None => DepGraph::new_disabled(),
Some(future) => {
......@@ -194,7 +213,7 @@ pub fn dep_graph(&self) -> Result<&Query<DepGraph>> {
pub fn lower_to_hir(
&self,
) -> Result<&Query<(Steal<hir::map::Forest>, Steal<ResolverOutputs>)>> {
self.queries.lower_to_hir.compute(|| {
self.lower_to_hir.compute(|| {
let expansion_result = self.expansion()?;
let peeked = expansion_result.peek();
let krate = &peeked.0;
......@@ -214,17 +233,17 @@ pub fn lower_to_hir(
}
pub fn prepare_outputs(&self) -> Result<&Query<OutputFilenames>> {
self.queries.prepare_outputs.compute(|| {
self.prepare_outputs.compute(|| {
let expansion_result = self.expansion()?;
let (krate, boxed_resolver, _) = &*expansion_result.peek();
let crate_name = self.crate_name()?;
let crate_name = crate_name.peek();
passes::prepare_outputs(self.session(), self, &krate, &boxed_resolver, &crate_name)
passes::prepare_outputs(self.session(), self.compiler, &krate, &boxed_resolver, &crate_name)
})
}
pub fn global_ctxt(&self) -> Result<&Query<BoxedGlobalCtxt>> {
self.queries.global_ctxt.compute(|| {
self.global_ctxt.compute(|| {
let crate_name = self.crate_name()?.peek().clone();
let outputs = self.prepare_outputs()?.peek().clone();
let lint_store = self.expansion()?.peek().2.clone();
......@@ -232,7 +251,7 @@ pub fn global_ctxt(&self) -> Result<&Query<BoxedGlobalCtxt>> {
let hir = hir.peek();
let (hir_forest, resolver_outputs) = &*hir;
Ok(passes::create_global_ctxt(
self,
self.compiler,
lint_store,
hir_forest.steal(),
resolver_outputs.steal(),
......@@ -242,7 +261,7 @@ pub fn global_ctxt(&self) -> Result<&Query<BoxedGlobalCtxt>> {
}
pub fn ongoing_codegen(&self) -> Result<&Query<Box<dyn Any>>> {
self.queries.ongoing_codegen.compute(|| {
self.ongoing_codegen.compute(|| {
let outputs = self.prepare_outputs()?;
self.global_ctxt()?.peek_mut().enter(|tcx| {
tcx.analysis(LOCAL_CRATE).ok();
......@@ -260,7 +279,7 @@ pub fn ongoing_codegen(&self) -> Result<&Query<Box<dyn Any>>> {
}
pub fn link(&self) -> Result<&Query<()>> {
self.queries.link.compute(|| {
self.link.compute(|| {
let sess = self.session();
let ongoing_codegen = self.ongoing_codegen()?.take();
......@@ -275,6 +294,20 @@ pub fn link(&self) -> Result<&Query<()>> {
Ok(())
})
}
}
impl Compiler {
// This method is different to all the other methods in `Compiler` because
// it lacks a `Queries` entry. It's also not currently used. It does serve
// as an example of how `Compiler` can be used, with additional steps added
// between some passes. And see `rustc_driver::run_compiler` for a more
// complex example.
pub fn enter<'c, F, T>(&'c self, f: F) -> Result<T>
where F: for<'q> FnOnce(&'q Queries<'c>) -> Result<T>
{
let queries = Queries::new(&self);
f(&queries)
}
// This method is different to all the other methods in `Compiler` because
// it lacks a `Queries` entry. It's also not currently used. It does serve
......@@ -282,24 +315,26 @@ pub fn link(&self) -> Result<&Query<()>> {
// between some passes. And see `rustc_driver::run_compiler` for a more
// complex example.
pub fn compile(&self) -> Result<()> {
self.prepare_outputs()?;
self.enter(|queries| {
queries.prepare_outputs()?;
if self.session().opts.output_types.contains_key(&OutputType::DepInfo)
&& self.session().opts.output_types.len() == 1
{
return Ok(())
}
if self.session().opts.output_types.contains_key(&OutputType::DepInfo)
&& self.session().opts.output_types.len() == 1
{
return Ok(())
}
self.global_ctxt()?;
queries.global_ctxt()?;
// Drop AST after creating GlobalCtxt to free memory.
mem::drop(self.expansion()?.take());
// Drop AST after creating GlobalCtxt to free memory.
mem::drop(queries.expansion()?.take());
self.ongoing_codegen()?;
queries.ongoing_codegen()?;
// Drop GlobalCtxt after starting codegen to free memory.
mem::drop(self.global_ctxt()?.take());
// Drop GlobalCtxt after starting codegen to free memory.
mem::drop(queries.global_ctxt()?.take());
self.link().map(|_| ())
queries.link().map(|_| ())
})
}
}
......@@ -346,34 +346,38 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt
interface::run_compiler_in_existing_thread_pool(config, |compiler| {
let sess = compiler.session();
// We need to hold on to the complete resolver, so we cause everything to be
// cloned for the analysis passes to use. Suboptimal, but necessary in the
// current architecture.
let resolver = {
let parts = abort_on_err(compiler.expansion(), sess).peek();
let resolver = parts.1.borrow();
// Before we actually clone it, let's force all the extern'd crates to
// actually be loaded, just in case they're only referred to inside
// intra-doc-links
resolver.borrow_mut().access(|resolver| {
for extern_name in &extern_names {
resolver.resolve_str_path_error(DUMMY_SP, extern_name, TypeNS, CRATE_NODE_ID)
.unwrap_or_else(
|()| panic!("Unable to resolve external crate {}", extern_name)
);
}
});
let (resolver, mut global_ctxt) = compiler.enter(|queries| {
// We need to hold on to the complete resolver, so we cause everything to be
// cloned for the analysis passes to use. Suboptimal, but necessary in the
// current architecture.
let resolver = {
let parts = abort_on_err(queries.expansion(), sess).peek();
let resolver = parts.1.borrow();
// Before we actually clone it, let's force all the extern'd crates to
// actually be loaded, just in case they're only referred to inside
// intra-doc-links
resolver.borrow_mut().access(|resolver| {
for extern_name in &extern_names {
resolver.resolve_str_path_error(DUMMY_SP, extern_name, TypeNS, CRATE_NODE_ID)
.unwrap_or_else(
|()| panic!("Unable to resolve external crate {}", extern_name)
);
}
});
// Now we're good to clone the resolver because everything should be loaded
resolver.clone()
};
// Now we're good to clone the resolver because everything should be loaded
resolver.clone()
};
if sess.has_errors() {
sess.fatal("Compilation failed, aborting rustdoc");
}
if sess.has_errors() {
sess.fatal("Compilation failed, aborting rustdoc");
}
let global_ctxt = abort_on_err(queries.global_ctxt(), sess).take();
let mut global_ctxt = abort_on_err(compiler.global_ctxt(), sess).take();
Ok((resolver, global_ctxt))
}).unwrap();
global_ctxt.enter(|tcx| {
tcx.analysis(LOCAL_CRATE).ok();
......
......@@ -86,22 +86,25 @@ pub fn run(options: Options) -> i32 {
let display_warnings = options.display_warnings;
let tests = interface::run_compiler(config, |compiler| -> Result<_, ErrorReported> {
let lower_to_hir = compiler.lower_to_hir()?;
let mut opts = scrape_test_config(lower_to_hir.peek().0.borrow().krate());
opts.display_warnings |= options.display_warnings;
let enable_per_target_ignores = options.enable_per_target_ignores;
let mut collector = Collector::new(
compiler.crate_name()?.peek().to_string(),
options,
false,
opts,
Some(compiler.source_map().clone()),
None,
enable_per_target_ignores,
);
let mut global_ctxt = compiler.global_ctxt()?.take();
let (mut collector, mut global_ctxt) = compiler.enter(|queries| {
let lower_to_hir = queries.lower_to_hir()?;
let mut opts = scrape_test_config(lower_to_hir.peek().0.borrow().krate());
opts.display_warnings |= options.display_warnings;
let enable_per_target_ignores = options.enable_per_target_ignores;
let collector = Collector::new(
queries.crate_name()?.peek().to_string(),
options,
false,
opts,
Some(compiler.source_map().clone()),
None,
enable_per_target_ignores,
);
let global_ctxt = queries.global_ctxt()?.take();
Ok((collector, global_ctxt))
})?;
global_ctxt.enter(|tcx| {
let krate = tcx.hir().krate();
let mut hir_collector = HirCollector {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册