Skip to content

Commit

Permalink
Rollup merge of rust-lang#102769 - nnethercote:rustdoc-startup, r=jyn514
Browse files Browse the repository at this point in the history
Clean up rustdoc startup

Startup is pretty hairy, in both rustdoc and rustc. The first commit here improves the rustdoc situation quite a bit. The remaining commits are smaller but also help.

Best reviewed one commit at a time.

r? `@jyn514`
  • Loading branch information
Dylan-DPC committed Oct 10, 2022
2 parents 8d606ef + 1f0463a commit 133e945
Show file tree
Hide file tree
Showing 5 changed files with 109 additions and 121 deletions.
102 changes: 48 additions & 54 deletions compiler/rustc_interface/src/interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -276,67 +276,61 @@ pub struct Config {
pub registry: Registry,
}

pub fn create_compiler_and_run<R>(config: Config, f: impl FnOnce(&Compiler) -> R) -> R {
crate::callbacks::setup_callbacks();

let registry = &config.registry;
let (mut sess, codegen_backend) = util::create_session(
config.opts,
config.crate_cfg,
config.crate_check_cfg,
config.diagnostic_output,
config.file_loader,
config.input_path.clone(),
config.lint_caps,
config.make_codegen_backend,
registry.clone(),
);

if let Some(parse_sess_created) = config.parse_sess_created {
parse_sess_created(
&mut Lrc::get_mut(&mut sess)
.expect("create_session() should never share the returned session")
.parse_sess,
);
}

let temps_dir = sess.opts.unstable_opts.temps_dir.as_ref().map(|o| PathBuf::from(&o));

let compiler = Compiler {
sess,
codegen_backend,
input: config.input,
input_path: config.input_path,
output_dir: config.output_dir,
output_file: config.output_file,
temps_dir,
register_lints: config.register_lints,
override_queries: config.override_queries,
};

rustc_span::with_source_map(compiler.sess.parse_sess.clone_source_map(), move || {
let r = {
let _sess_abort_error = OnDrop(|| {
compiler.sess.finish_diagnostics(registry);
});

f(&compiler)
};

let prof = compiler.sess.prof.clone();
prof.generic_activity("drop_compiler").run(move || drop(compiler));
r
})
}

// JUSTIFICATION: before session exists, only config
#[allow(rustc::bad_opt_access)]
pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Send) -> R {
trace!("run_compiler");
util::run_in_thread_pool_with_globals(
config.opts.edition,
config.opts.unstable_opts.threads,
|| create_compiler_and_run(config, f),
|| {
crate::callbacks::setup_callbacks();

let registry = &config.registry;
let (mut sess, codegen_backend) = util::create_session(
config.opts,
config.crate_cfg,
config.crate_check_cfg,
config.diagnostic_output,
config.file_loader,
config.input_path.clone(),
config.lint_caps,
config.make_codegen_backend,
registry.clone(),
);

if let Some(parse_sess_created) = config.parse_sess_created {
parse_sess_created(&mut sess.parse_sess);
}

let temps_dir = sess.opts.unstable_opts.temps_dir.as_ref().map(|o| PathBuf::from(&o));

let compiler = Compiler {
sess: Lrc::new(sess),
codegen_backend: Lrc::new(codegen_backend),
input: config.input,
input_path: config.input_path,
output_dir: config.output_dir,
output_file: config.output_file,
temps_dir,
register_lints: config.register_lints,
override_queries: config.override_queries,
};

rustc_span::with_source_map(compiler.sess.parse_sess.clone_source_map(), move || {
let r = {
let _sess_abort_error = OnDrop(|| {
compiler.sess.finish_diagnostics(registry);
});

f(&compiler)
};

let prof = compiler.sess.prof.clone();
prof.generic_activity("drop_compiler").run(move || drop(compiler));
r
})
},
)
}

Expand Down
45 changes: 21 additions & 24 deletions compiler/rustc_interface/src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ use rustc_codegen_ssa::traits::CodegenBackend;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
#[cfg(parallel_compiler)]
use rustc_data_structures::jobserver;
use rustc_data_structures::sync::Lrc;
use rustc_errors::registry::Registry;
#[cfg(parallel_compiler)]
use rustc_middle::ty::tls;
Expand Down Expand Up @@ -73,7 +72,7 @@ pub fn create_session(
Box<dyn FnOnce(&config::Options) -> Box<dyn CodegenBackend> + Send>,
>,
descriptions: Registry,
) -> (Lrc<Session>, Lrc<Box<dyn CodegenBackend>>) {
) -> (Session, Box<dyn CodegenBackend>) {
let codegen_backend = if let Some(make_codegen_backend) = make_codegen_backend {
make_codegen_backend(&sopts)
} else {
Expand Down Expand Up @@ -121,7 +120,7 @@ pub fn create_session(
sess.parse_sess.config = cfg;
sess.parse_sess.check_config = check_cfg;

(Lrc::new(sess), Lrc::new(codegen_backend))
(sess, codegen_backend)
}

const STACK_SIZE: usize = 8 * 1024 * 1024;
Expand All @@ -132,33 +131,31 @@ fn get_stack_size() -> Option<usize> {
env::var_os("RUST_MIN_STACK").is_none().then_some(STACK_SIZE)
}

/// Like a `thread::Builder::spawn` followed by a `join()`, but avoids the need
/// for `'static` bounds.
#[cfg(not(parallel_compiler))]
fn scoped_thread<F: FnOnce() -> R + Send, R: Send>(cfg: thread::Builder, f: F) -> R {
// SAFETY: join() is called immediately, so any closure captures are still
// alive.
match unsafe { cfg.spawn_unchecked(f) }.unwrap().join() {
Ok(v) => v,
Err(e) => panic::resume_unwind(e),
}
}

#[cfg(not(parallel_compiler))]
pub fn run_in_thread_pool_with_globals<F: FnOnce() -> R + Send, R: Send>(
pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce() -> R + Send, R: Send>(
edition: Edition,
_threads: usize,
f: F,
) -> R {
let mut cfg = thread::Builder::new().name("rustc".to_string());

if let Some(size) = get_stack_size() {
cfg = cfg.stack_size(size);
}
// The thread pool is a single thread in the non-parallel compiler.
thread::scope(|s| {
let mut builder = thread::Builder::new().name("rustc".to_string());
if let Some(size) = get_stack_size() {
builder = builder.stack_size(size);
}

let main_handler = move || rustc_span::create_session_globals_then(edition, f);
// `unwrap` is ok here because `spawn_scoped` only panics if the thread
// name contains null bytes.
let r = builder
.spawn_scoped(s, move || rustc_span::create_session_globals_then(edition, f))
.unwrap()
.join();

scoped_thread(cfg, main_handler)
match r {
Ok(v) => v,
Err(e) => panic::resume_unwind(e),
}
})
}

/// Creates a new thread and forwards information in thread locals to it.
Expand All @@ -177,7 +174,7 @@ unsafe fn handle_deadlock() {
}

#[cfg(parallel_compiler)]
pub fn run_in_thread_pool_with_globals<F: FnOnce() -> R + Send, R: Send>(
pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce() -> R + Send, R: Send>(
edition: Edition,
threads: usize,
f: F,
Expand Down
9 changes: 4 additions & 5 deletions src/librustdoc/doctest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ use rustc_session::{lint, DiagnosticOutput, Session};
use rustc_span::edition::Edition;
use rustc_span::source_map::SourceMap;
use rustc_span::symbol::sym;
use rustc_span::Symbol;
use rustc_span::{BytePos, FileName, Pos, Span, DUMMY_SP};
use rustc_target::spec::TargetTriple;
use tempfile::Builder as TempFileBuilder;
Expand Down Expand Up @@ -125,7 +124,7 @@ pub(crate) fn run(options: RustdocOptions) -> Result<(), ErrorGuaranteed> {
let opts = scrape_test_config(crate_attrs);
let enable_per_target_ignores = options.enable_per_target_ignores;
let mut collector = Collector::new(
tcx.crate_name(LOCAL_CRATE),
tcx.crate_name(LOCAL_CRATE).to_string(),
options,
false,
opts,
Expand Down Expand Up @@ -909,7 +908,7 @@ pub(crate) struct Collector {
rustdoc_options: RustdocOptions,
use_headers: bool,
enable_per_target_ignores: bool,
crate_name: Symbol,
crate_name: String,
opts: GlobalTestOptions,
position: Span,
source_map: Option<Lrc<SourceMap>>,
Expand All @@ -921,7 +920,7 @@ pub(crate) struct Collector {

impl Collector {
pub(crate) fn new(
crate_name: Symbol,
crate_name: String,
rustdoc_options: RustdocOptions,
use_headers: bool,
opts: GlobalTestOptions,
Expand Down Expand Up @@ -984,7 +983,7 @@ impl Tester for Collector {
fn add_test(&mut self, test: String, config: LangString, line: usize) {
let filename = self.get_filename();
let name = self.generate_name(line, &filename);
let crate_name = self.crate_name.to_string();
let crate_name = self.crate_name.clone();
let opts = self.opts.clone();
let edition = config.edition.unwrap_or(self.rustdoc_options.edition);
let rustdoc_options = self.rustdoc_options.clone();
Expand Down
69 changes: 33 additions & 36 deletions src/librustdoc/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -674,39 +674,6 @@ fn usage(argv0: &str) {
/// A result type used by several functions under `main()`.
type MainResult = Result<(), ErrorGuaranteed>;

fn main_args(at_args: &[String]) -> MainResult {
let args = rustc_driver::args::arg_expand_all(at_args);

let mut options = getopts::Options::new();
for option in opts() {
(option.apply)(&mut options);
}
let matches = match options.parse(&args[1..]) {
Ok(m) => m,
Err(err) => {
early_error(ErrorOutputType::default(), &err.to_string());
}
};

// Note that we discard any distinction between different non-zero exit
// codes from `from_matches` here.
let options = match config::Options::from_matches(&matches, args) {
Ok(opts) => opts,
Err(code) => {
return if code == 0 {
Ok(())
} else {
Err(ErrorGuaranteed::unchecked_claim_error_was_emitted())
};
}
};
rustc_interface::util::run_in_thread_pool_with_globals(
options.edition,
1, // this runs single-threaded, even in a parallel compiler
move || main_options(options),
)
}

fn wrap_return(diag: &rustc_errors::Handler, res: Result<(), String>) -> MainResult {
match res {
Ok(()) => Ok(()),
Expand Down Expand Up @@ -737,7 +704,33 @@ fn run_renderer<'tcx, T: formats::FormatRenderer<'tcx>>(
}
}

fn main_options(options: config::Options) -> MainResult {
fn main_args(at_args: &[String]) -> MainResult {
let args = rustc_driver::args::arg_expand_all(at_args);

let mut options = getopts::Options::new();
for option in opts() {
(option.apply)(&mut options);
}
let matches = match options.parse(&args[1..]) {
Ok(m) => m,
Err(err) => {
early_error(ErrorOutputType::default(), &err.to_string());
}
};

// Note that we discard any distinction between different non-zero exit
// codes from `from_matches` here.
let options = match config::Options::from_matches(&matches, args) {
Ok(opts) => opts,
Err(code) => {
return if code == 0 {
Ok(())
} else {
Err(ErrorGuaranteed::unchecked_claim_error_was_emitted())
};
}
};

let diag = core::new_handler(
options.error_format,
None,
Expand All @@ -749,9 +742,12 @@ fn main_options(options: config::Options) -> MainResult {
(true, true) => return wrap_return(&diag, markdown::test(options)),
(true, false) => return doctest::run(options),
(false, true) => {
// Session globals are required for symbol interning.
return wrap_return(
&diag,
markdown::render(&options.input, options.render_options, options.edition),
rustc_span::create_session_globals_then(options.edition, || {
markdown::render(&options.input, options.render_options, options.edition)
}),
);
}
(false, false) => {}
Expand All @@ -777,9 +773,10 @@ fn main_options(options: config::Options) -> MainResult {
let render_options = options.render_options.clone();
let scrape_examples_options = options.scrape_examples_options.clone();
let document_private = options.render_options.document_private;

let config = core::create_config(options);

interface::create_compiler_and_run(config, |compiler| {
interface::run_compiler(config, |compiler| {
let sess = compiler.session();

if sess.opts.describe_lints {
Expand Down
5 changes: 3 additions & 2 deletions src/librustdoc/markdown.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ use std::path::Path;

use rustc_span::edition::Edition;
use rustc_span::source_map::DUMMY_SP;
use rustc_span::Symbol;

use crate::config::{Options, RenderOptions};
use crate::doctest::{Collector, GlobalTestOptions};
Expand Down Expand Up @@ -36,6 +35,8 @@ fn extract_leading_metadata(s: &str) -> (Vec<&str>, &str) {

/// Render `input` (e.g., "foo.md") into an HTML file in `output`
/// (e.g., output = "bar" => "bar/foo.html").
///
/// Requires session globals to be available, for symbol interning.
pub(crate) fn render<P: AsRef<Path>>(
input: P,
options: RenderOptions,
Expand Down Expand Up @@ -133,7 +134,7 @@ pub(crate) fn test(options: Options) -> Result<(), String> {
let mut opts = GlobalTestOptions::default();
opts.no_crate_inject = true;
let mut collector = Collector::new(
Symbol::intern(&options.input.display().to_string()),
options.input.display().to_string(),
options.clone(),
true,
opts,
Expand Down

0 comments on commit 133e945

Please sign in to comment.