Skip to content

Commit 0aa4956

Browse files
committed
Use #[thread_local] instead of thread_local!
This avoid monomorphizing `LocalKey::try_with` 5 times for each query. It has the downside that destructors for the thread-local are never run; but we don't depend on the destructors for ImplicitContext itself anywhere.
1 parent 29d76cc commit 0aa4956

File tree

2 files changed

+73
-46
lines changed

2 files changed

+73
-46
lines changed

compiler/rustc_middle/src/lib.rs

+3
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#![feature(generators)]
3434
#![feature(get_mut_unchecked)]
3535
#![feature(if_let_guard)]
36+
#![feature(inline_const)]
3637
#![feature(iter_from_generator)]
3738
#![feature(negative_impls)]
3839
#![feature(never_type)]
@@ -47,6 +48,8 @@
4748
#![feature(rustc_attrs)]
4849
#![feature(control_flow_enum)]
4950
#![feature(associated_type_defaults)]
51+
#![feature(thread_local)]
52+
#![feature(cfg_target_thread_local)]
5053
#![feature(trusted_step)]
5154
#![feature(try_blocks)]
5255
#![feature(try_reserve_kind)]

compiler/rustc_middle/src/ty/context.rs

+70-46
Original file line numberDiff line numberDiff line change
@@ -1215,11 +1215,77 @@ pub mod tls {
12151215
use std::mem;
12161216
use thin_vec::ThinVec;
12171217

1218-
#[cfg(not(parallel_compiler))]
1219-
use std::cell::Cell;
1220-
12211218
#[cfg(parallel_compiler)]
1222-
use rustc_rayon_core as rayon_core;
1219+
mod tls_impl {
1220+
use rustc_rayon_core as rayon_core;
1221+
1222+
/// Sets Rayon's thread-local variable, which is preserved for Rayon jobs
1223+
/// to `value` during the call to `f`. It is restored to its previous value after.
1224+
/// This is used to set the pointer to the new `ImplicitCtxt`.
1225+
#[inline]
1226+
pub(super) fn set_tlv<F: FnOnce() -> R, R>(value: usize, f: F) -> R {
1227+
rayon_core::tlv::with(value, f)
1228+
}
1229+
1230+
/// Gets Rayon's thread-local variable, which is preserved for Rayon jobs.
1231+
/// This is used to get the pointer to the current `ImplicitCtxt`.
1232+
#[inline]
1233+
pub fn get_tlv() -> usize {
1234+
rayon_core::tlv::get()
1235+
}
1236+
}
1237+
1238+
#[cfg(all(not(parallel_compiler), target_thread_local))]
1239+
mod tls_impl {
1240+
use std::cell::Cell;
1241+
1242+
/// A thread local variable that stores a pointer to the current `ImplicitCtxt`.
1243+
#[thread_local]
1244+
static TLV: Cell<usize> = Cell::new(0);
1245+
1246+
/// Sets TLV to `value` during the call to `f`.
1247+
/// It is restored to its previous value after.
1248+
/// This is used to set the pointer to the new `ImplicitCtxt`.
1249+
#[inline]
1250+
pub(super) fn set_tlv<F: FnOnce() -> R, R>(value: usize, f: F) -> R {
1251+
let old = get_tlv();
1252+
let _reset = rustc_data_structures::OnDrop(move || TLV.set(old));
1253+
TLV.set(value);
1254+
f()
1255+
}
1256+
1257+
/// Gets the pointer to the current `ImplicitCtxt`.
1258+
#[inline]
1259+
pub(super) fn get_tlv() -> usize {
1260+
TLV.get()
1261+
}
1262+
}
1263+
1264+
#[cfg(all(not(parallel_compiler), not(target_thread_local)))]
1265+
/// Ideally this wouldn't be necessary, but `#[thread_local]` uses OS built-ins which don't work on every platform.
1266+
/// The reason we use `#[thread_local]` at all is to avoid monomorphizing `LocalKey::with` for each `F` passed to `set_tlv`.
1267+
mod tls_impl {
1268+
use std::cell::Cell;
1269+
1270+
thread_local! {
1271+
static TLV: Cell<usize> = Cell::new(0);
1272+
}
1273+
1274+
#[inline]
1275+
pub(super) fn set_tlv<F: FnOnce() -> R, R>(value: usize, f: F) -> R {
1276+
let old = get_tlv();
1277+
let _reset = rustc_data_structures::OnDrop(move || TLV.with(|tlv| tlv.set(old)));
1278+
TLV.with(|tlv| tlv.set(value));
1279+
f()
1280+
}
1281+
1282+
#[inline]
1283+
pub(super) fn get_tlv() -> usize {
1284+
TLV.with(|tlv| tlv.get())
1285+
}
1286+
}
1287+
1288+
use tls_impl::{get_tlv, set_tlv};
12231289

12241290
/// This is the implicit state of rustc. It contains the current
12251291
/// `TyCtxt` and query. It is updated when creating a local interner or
@@ -1260,48 +1326,6 @@ pub mod tls {
12601326
}
12611327
}
12621328

1263-
/// Sets Rayon's thread-local variable, which is preserved for Rayon jobs
1264-
/// to `value` during the call to `f`. It is restored to its previous value after.
1265-
/// This is used to set the pointer to the new `ImplicitCtxt`.
1266-
#[cfg(parallel_compiler)]
1267-
#[inline]
1268-
fn set_tlv<F: FnOnce() -> R, R>(value: usize, f: F) -> R {
1269-
rayon_core::tlv::with(value, f)
1270-
}
1271-
1272-
/// Gets Rayon's thread-local variable, which is preserved for Rayon jobs.
1273-
/// This is used to get the pointer to the current `ImplicitCtxt`.
1274-
#[cfg(parallel_compiler)]
1275-
#[inline]
1276-
pub fn get_tlv() -> usize {
1277-
rayon_core::tlv::get()
1278-
}
1279-
1280-
#[cfg(not(parallel_compiler))]
1281-
thread_local! {
1282-
/// A thread local variable that stores a pointer to the current `ImplicitCtxt`.
1283-
static TLV: Cell<usize> = const { Cell::new(0) };
1284-
}
1285-
1286-
/// Sets TLV to `value` during the call to `f`.
1287-
/// It is restored to its previous value after.
1288-
/// This is used to set the pointer to the new `ImplicitCtxt`.
1289-
#[cfg(not(parallel_compiler))]
1290-
#[inline]
1291-
fn set_tlv<F: FnOnce() -> R, R>(value: usize, f: F) -> R {
1292-
let old = get_tlv();
1293-
let _reset = rustc_data_structures::OnDrop(move || TLV.with(|tlv| tlv.set(old)));
1294-
TLV.with(|tlv| tlv.set(value));
1295-
f()
1296-
}
1297-
1298-
/// Gets the pointer to the current `ImplicitCtxt`.
1299-
#[cfg(not(parallel_compiler))]
1300-
#[inline]
1301-
fn get_tlv() -> usize {
1302-
TLV.with(|tlv| tlv.get())
1303-
}
1304-
13051329
/// Sets `context` as the new current `ImplicitCtxt` for the duration of the function `f`.
13061330
#[inline]
13071331
pub fn enter_context<'a, 'tcx, F, R>(context: &ImplicitCtxt<'a, 'tcx>, f: F) -> R

0 commit comments

Comments
 (0)