Auto merge of #74969 - nnethercote:rm-GCX_PTR, r=Mark-Simulacrum

Remove `GCX_PTR`.

We store an `ImplicitCtxt` pointer in a thread-local value (TLV). This allows
implicit access to a `GlobalCtxt` and some other things.

We also store a `GlobalCtxt` pointer in `GCX_PTR`. This is always the same
`GlobalCtxt` as the one within the `ImplicitCtxt` pointer in TLV. `GCX_PTR`
is only used in the parallel compiler's `handle_deadlock()` function.

This commit does the following.
- It removes `GCX_PTR`.
- It also adds `ImplicitCtxt::new()`, which constructs an `ImplicitCtxt` from a
  `GlobalCtxt`. `ImplicitCtxt::new()` + `tls::enter_context()` is now
  equivalent to the old `tls::enter_global()`.
- Makes `tls::get_tlv()` public for the parallel compiler, because it's
  now used in `handle_deadlock()`.

r? @petrochenkov
This commit is contained in:
bors 2020-08-03 01:50:25 +00:00
commit 8244b1b114
9 changed files with 36 additions and 79 deletions

View File

@ -3677,7 +3677,6 @@ dependencies = [
"rustc_session", "rustc_session",
"rustc_span", "rustc_span",
"rustc_target", "rustc_target",
"scoped-tls",
"smallvec 1.4.0", "smallvec 1.4.0",
"tracing", "tracing",
] ]

View File

@ -199,8 +199,8 @@ impl CanonicalizeRegionMode for CanonicalizeQueryResponse {
// rust-lang/rust#57464: `impl Trait` can leak local // rust-lang/rust#57464: `impl Trait` can leak local
// scopes (in manner violating typeck). Therefore, use // scopes (in manner violating typeck). Therefore, use
// `delay_span_bug` to allow type error over an ICE. // `delay_span_bug` to allow type error over an ICE.
ty::tls::with_context(|c| { ty::tls::with(|tcx| {
c.tcx.sess.delay_span_bug( tcx.sess.delay_span_bug(
rustc_span::DUMMY_SP, rustc_span::DUMMY_SP,
&format!("unexpected region in query response: `{:?}`", r), &format!("unexpected region in query response: `{:?}`", r),
); );

View File

@ -752,7 +752,8 @@ impl<'tcx> QueryContext<'tcx> {
where where
F: FnOnce(TyCtxt<'tcx>) -> R, F: FnOnce(TyCtxt<'tcx>) -> R,
{ {
ty::tls::enter_global(self.0, f) let icx = ty::tls::ImplicitCtxt::new(self.0);
ty::tls::enter_context(&icx, |_| f(icx.tcx))
} }
pub fn print_stats(&mut self) { pub fn print_stats(&mut self) {
@ -811,8 +812,9 @@ pub fn create_global_ctxt<'tcx>(
}); });
// Do some initialization of the DepGraph that can only be done with the tcx available. // Do some initialization of the DepGraph that can only be done with the tcx available.
ty::tls::enter_global(&gcx, |tcx| { let icx = ty::tls::ImplicitCtxt::new(&gcx);
tcx.sess.time("dep_graph_tcx_init", || rustc_incremental::dep_graph_tcx_init(tcx)); ty::tls::enter_context(&icx, |_| {
icx.tcx.sess.time("dep_graph_tcx_init", || rustc_incremental::dep_graph_tcx_init(icx.tcx));
}); });
QueryContext(gcx) QueryContext(gcx)

View File

@ -10,10 +10,9 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
#[cfg(parallel_compiler)] #[cfg(parallel_compiler)]
use rustc_data_structures::jobserver; use rustc_data_structures::jobserver;
use rustc_data_structures::stable_hasher::StableHasher; use rustc_data_structures::stable_hasher::StableHasher;
use rustc_data_structures::sync::{Lock, Lrc}; use rustc_data_structures::sync::Lrc;
use rustc_errors::registry::Registry; use rustc_errors::registry::Registry;
use rustc_metadata::dynamic_lib::DynamicLibrary; use rustc_metadata::dynamic_lib::DynamicLibrary;
use rustc_middle::ty;
use rustc_resolve::{self, Resolver}; use rustc_resolve::{self, Resolver};
use rustc_session as session; use rustc_session as session;
use rustc_session::config::{self, CrateType}; use rustc_session::config::{self, CrateType};
@ -144,13 +143,11 @@ pub fn setup_callbacks_and_run_in_thread_pool_with_globals<F: FnOnce() -> R + Se
let main_handler = move || { let main_handler = move || {
rustc_ast::with_session_globals(edition, || { rustc_ast::with_session_globals(edition, || {
ty::tls::GCX_PTR.set(&Lock::new(0), || {
if let Some(stderr) = stderr { if let Some(stderr) = stderr {
io::set_panic(Some(box Sink(stderr.clone()))); io::set_panic(Some(box Sink(stderr.clone())));
} }
f() f()
}) })
})
}; };
scoped_thread(cfg, main_handler) scoped_thread(cfg, main_handler)
@ -163,6 +160,7 @@ pub fn setup_callbacks_and_run_in_thread_pool_with_globals<F: FnOnce() -> R + Se
stderr: &Option<Arc<Mutex<Vec<u8>>>>, stderr: &Option<Arc<Mutex<Vec<u8>>>>,
f: F, f: F,
) -> R { ) -> R {
use rustc_middle::ty;
crate::callbacks::setup_callbacks(); crate::callbacks::setup_callbacks();
let mut config = rayon::ThreadPoolBuilder::new() let mut config = rayon::ThreadPoolBuilder::new()
@ -189,14 +187,12 @@ pub fn setup_callbacks_and_run_in_thread_pool_with_globals<F: FnOnce() -> R + Se
let main_handler = move |thread: rayon::ThreadBuilder| { let main_handler = move |thread: rayon::ThreadBuilder| {
rustc_ast::SESSION_GLOBALS.set(ast_session_globals, || { rustc_ast::SESSION_GLOBALS.set(ast_session_globals, || {
rustc_span::SESSION_GLOBALS.set(span_session_globals, || { rustc_span::SESSION_GLOBALS.set(span_session_globals, || {
ty::tls::GCX_PTR.set(&Lock::new(0), || {
if let Some(stderr) = stderr { if let Some(stderr) = stderr {
io::set_panic(Some(box Sink(stderr.clone()))); io::set_panic(Some(box Sink(stderr.clone())));
} }
thread.run() thread.run()
}) })
}) })
})
}; };
config.build_scoped(main_handler, with_pool).unwrap() config.build_scoped(main_handler, with_pool).unwrap()

View File

@ -12,7 +12,6 @@ doctest = false
[dependencies] [dependencies]
rustc_arena = { path = "../librustc_arena" } rustc_arena = { path = "../librustc_arena" }
bitflags = "1.2.1" bitflags = "1.2.1"
scoped-tls = "1.0"
log = { package = "tracing", version = "0.1" } log = { package = "tracing", version = "0.1" }
rustc-rayon-core = "0.3.0" rustc-rayon-core = "0.3.0"
polonius-engine = "0.12.0" polonius-engine = "0.12.0"

View File

@ -55,8 +55,6 @@
#[macro_use] #[macro_use]
extern crate bitflags; extern crate bitflags;
#[macro_use] #[macro_use]
extern crate scoped_tls;
#[macro_use]
extern crate rustc_macros; extern crate rustc_macros;
#[macro_use] #[macro_use]
extern crate rustc_data_structures; extern crate rustc_data_structures;

View File

@ -242,9 +242,9 @@ impl From<ErrorHandled> for InterpErrorInfo<'_> {
impl<'tcx> From<InterpError<'tcx>> for InterpErrorInfo<'tcx> { impl<'tcx> From<InterpError<'tcx>> for InterpErrorInfo<'tcx> {
fn from(kind: InterpError<'tcx>) -> Self { fn from(kind: InterpError<'tcx>) -> Self {
let capture_backtrace = tls::with_context_opt(|ctxt| { let capture_backtrace = tls::with_opt(|tcx| {
if let Some(ctxt) = ctxt { if let Some(tcx) = tcx {
*Lock::borrow(&ctxt.tcx.sess.ctfe_backtrace) *Lock::borrow(&tcx.sess.ctfe_backtrace)
} else { } else {
CtfeBacktrace::Disabled CtfeBacktrace::Disabled
} }

View File

@ -1632,7 +1632,6 @@ pub mod tls {
use crate::ty::query; use crate::ty::query;
use rustc_data_structures::sync::{self, Lock}; use rustc_data_structures::sync::{self, Lock};
use rustc_data_structures::thin_vec::ThinVec; use rustc_data_structures::thin_vec::ThinVec;
use rustc_data_structures::OnDrop;
use rustc_errors::Diagnostic; use rustc_errors::Diagnostic;
use std::mem; use std::mem;
@ -1649,8 +1648,7 @@ pub mod tls {
/// in this module. /// in this module.
#[derive(Clone)] #[derive(Clone)]
pub struct ImplicitCtxt<'a, 'tcx> { pub struct ImplicitCtxt<'a, 'tcx> {
/// The current `TyCtxt`. Initially created by `enter_global` and updated /// The current `TyCtxt`.
/// by `enter_local` with a new local interner.
pub tcx: TyCtxt<'tcx>, pub tcx: TyCtxt<'tcx>,
/// The current query job, if any. This is updated by `JobOwner::start` in /// The current query job, if any. This is updated by `JobOwner::start` in
@ -1669,6 +1667,13 @@ pub mod tls {
pub task_deps: Option<&'a Lock<TaskDeps>>, pub task_deps: Option<&'a Lock<TaskDeps>>,
} }
impl<'a, 'tcx> ImplicitCtxt<'a, 'tcx> {
pub fn new(gcx: &'tcx GlobalCtxt<'tcx>) -> Self {
let tcx = TyCtxt { gcx };
ImplicitCtxt { tcx, query: None, diagnostics: None, layout_depth: 0, task_deps: None }
}
}
/// Sets Rayon's thread-local variable, which is preserved for Rayon jobs /// Sets Rayon's thread-local variable, which is preserved for Rayon jobs
/// to `value` during the call to `f`. It is restored to its previous value after. /// to `value` during the call to `f`. It is restored to its previous value after.
/// This is used to set the pointer to the new `ImplicitCtxt`. /// This is used to set the pointer to the new `ImplicitCtxt`.
@ -1682,7 +1687,7 @@ pub mod tls {
/// This is used to get the pointer to the current `ImplicitCtxt`. /// This is used to get the pointer to the current `ImplicitCtxt`.
#[cfg(parallel_compiler)] #[cfg(parallel_compiler)]
#[inline] #[inline]
fn get_tlv() -> usize { pub fn get_tlv() -> usize {
rayon_core::tlv::get() rayon_core::tlv::get()
} }
@ -1699,7 +1704,7 @@ pub mod tls {
#[inline] #[inline]
fn set_tlv<F: FnOnce() -> R, R>(value: usize, f: F) -> R { fn set_tlv<F: FnOnce() -> R, R>(value: usize, f: F) -> R {
let old = get_tlv(); let old = get_tlv();
let _reset = OnDrop(move || TLV.with(|tlv| tlv.set(old))); let _reset = rustc_data_structures::OnDrop(move || TLV.with(|tlv| tlv.set(old)));
TLV.with(|tlv| tlv.set(value)); TLV.with(|tlv| tlv.set(value));
f() f()
} }
@ -1720,50 +1725,6 @@ pub mod tls {
set_tlv(context as *const _ as usize, || f(&context)) set_tlv(context as *const _ as usize, || f(&context))
} }
/// Enters `GlobalCtxt` by setting up librustc_ast callbacks and
/// creating a initial `TyCtxt` and `ImplicitCtxt`.
/// This happens once per rustc session and `TyCtxt`s only exists
/// inside the `f` function.
pub fn enter_global<'tcx, F, R>(gcx: &'tcx GlobalCtxt<'tcx>, f: F) -> R
where
F: FnOnce(TyCtxt<'tcx>) -> R,
{
// Update `GCX_PTR` to indicate there's a `GlobalCtxt` available.
GCX_PTR.with(|lock| {
*lock.lock() = gcx as *const _ as usize;
});
// Set `GCX_PTR` back to 0 when we exit.
let _on_drop = OnDrop(move || {
GCX_PTR.with(|lock| *lock.lock() = 0);
});
let tcx = TyCtxt { gcx };
let icx =
ImplicitCtxt { tcx, query: None, diagnostics: None, layout_depth: 0, task_deps: None };
enter_context(&icx, |_| f(tcx))
}
scoped_thread_local! {
/// Stores a pointer to the `GlobalCtxt` if one is available.
/// This is used to access the `GlobalCtxt` in the deadlock handler given to Rayon.
pub static GCX_PTR: Lock<usize>
}
/// Creates a `TyCtxt` and `ImplicitCtxt` based on the `GCX_PTR` thread local.
/// This is used in the deadlock handler.
pub unsafe fn with_global<F, R>(f: F) -> R
where
F: for<'tcx> FnOnce(TyCtxt<'tcx>) -> R,
{
let gcx = GCX_PTR.with(|lock| *lock.lock());
assert!(gcx != 0);
let gcx = &*(gcx as *const GlobalCtxt<'_>);
let tcx = TyCtxt { gcx };
let icx =
ImplicitCtxt { query: None, diagnostics: None, tcx, layout_depth: 0, task_deps: None };
enter_context(&icx, |_| f(tcx))
}
/// Allows access to the current `ImplicitCtxt` in a closure if one is available. /// Allows access to the current `ImplicitCtxt` in a closure if one is available.
#[inline] #[inline]
pub fn with_context_opt<F, R>(f: F) -> R pub fn with_context_opt<F, R>(f: F) -> R

View File

@ -10,18 +10,20 @@ use std::thread;
pub unsafe fn handle_deadlock() { pub unsafe fn handle_deadlock() {
let registry = rayon_core::Registry::current(); let registry = rayon_core::Registry::current();
let gcx_ptr = tls::GCX_PTR.with(|gcx_ptr| gcx_ptr as *const _); let context = tls::get_tlv();
let gcx_ptr = &*gcx_ptr; assert!(context != 0);
rustc_data_structures::sync::assert_sync::<tls::ImplicitCtxt<'_, '_>>();
let icx: &tls::ImplicitCtxt<'_, '_> = &*(context as *const tls::ImplicitCtxt<'_, '_>);
let span_session_globals = rustc_span::SESSION_GLOBALS.with(|ssg| ssg as *const _); let span_session_globals = rustc_span::SESSION_GLOBALS.with(|ssg| ssg as *const _);
let span_session_globals = &*span_session_globals; let span_session_globals = &*span_session_globals;
let ast_session_globals = rustc_ast::attr::SESSION_GLOBALS.with(|asg| asg as *const _); let ast_session_globals = rustc_ast::attr::SESSION_GLOBALS.with(|asg| asg as *const _);
let ast_session_globals = &*ast_session_globals; let ast_session_globals = &*ast_session_globals;
thread::spawn(move || { thread::spawn(move || {
tls::GCX_PTR.set(gcx_ptr, || { tls::enter_context(icx, |_| {
rustc_ast::attr::SESSION_GLOBALS.set(ast_session_globals, || { rustc_ast::attr::SESSION_GLOBALS.set(ast_session_globals, || {
rustc_span::SESSION_GLOBALS rustc_span::SESSION_GLOBALS
.set(span_session_globals, || tls::with_global(|tcx| deadlock(tcx, &registry))) .set(span_session_globals, || tls::with(|tcx| deadlock(tcx, &registry)))
}); });
}) })
}); });