Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[experimental] Use #[thread_local] instead of thread_local! in rustc_middle #106270

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions compiler/rustc_middle/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#![feature(generators)]
#![feature(get_mut_unchecked)]
#![feature(if_let_guard)]
#![feature(inline_const)]
#![feature(iter_from_generator)]
#![feature(negative_impls)]
#![feature(never_type)]
Expand All @@ -47,6 +48,8 @@
#![feature(rustc_attrs)]
#![feature(control_flow_enum)]
#![feature(associated_type_defaults)]
#![feature(thread_local)]
#![feature(cfg_target_thread_local)]
#![feature(trusted_step)]
#![feature(try_blocks)]
#![feature(try_reserve_kind)]
Expand Down
116 changes: 70 additions & 46 deletions compiler/rustc_middle/src/ty/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1215,11 +1215,77 @@ pub mod tls {
use std::mem;
use thin_vec::ThinVec;

#[cfg(not(parallel_compiler))]
use std::cell::Cell;

#[cfg(parallel_compiler)]
use rustc_rayon_core as rayon_core;
mod tls_impl {
use rustc_rayon_core as rayon_core;

/// 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.
/// This is used to set the pointer to the new `ImplicitCtxt`.
#[inline]
pub(super) fn set_tlv<F: FnOnce() -> R, R>(value: usize, f: F) -> R {
rayon_core::tlv::with(value, f)
}

/// Gets Rayon's thread-local variable, which is preserved for Rayon jobs.
/// This is used to get the pointer to the current `ImplicitCtxt`.
#[inline]
pub fn get_tlv() -> usize {
rayon_core::tlv::get()
}
}

#[cfg(all(not(parallel_compiler), target_thread_local))]
mod tls_impl {
use std::cell::Cell;

/// A thread local variable that stores a pointer to the current `ImplicitCtxt`.
#[thread_local]
static TLV: Cell<usize> = Cell::new(0);

/// Sets TLV 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`.
#[inline]
pub(super) fn set_tlv<F: FnOnce() -> R, R>(value: usize, f: F) -> R {
let old = get_tlv();
let _reset = rustc_data_structures::OnDrop(move || TLV.set(old));
TLV.set(value);
f()
}

/// Gets the pointer to the current `ImplicitCtxt`.
#[inline]
pub(super) fn get_tlv() -> usize {
TLV.get()
}
}

#[cfg(all(not(parallel_compiler), not(target_thread_local)))]
/// Ideally this wouldn't be necessary, but `#[thread_local]` uses OS built-ins which don't work on every platform.
/// The reason we use `#[thread_local]` at all is to avoid monomorphizing `LocalKey::with` for each `F` passed to `set_tlv`.
mod tls_impl {
use std::cell::Cell;

thread_local! {
static TLV: Cell<usize> = Cell::new(0);
}

#[inline]
pub(super) fn set_tlv<F: FnOnce() -> R, R>(value: usize, f: F) -> R {
let old = get_tlv();
let _reset = rustc_data_structures::OnDrop(move || TLV.with(|tlv| tlv.set(old)));
TLV.with(|tlv| tlv.set(value));
f()
}

#[inline]
pub(super) fn get_tlv() -> usize {
TLV.with(|tlv| tlv.get())
}
}

use tls_impl::{get_tlv, set_tlv};

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

/// 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.
/// This is used to set the pointer to the new `ImplicitCtxt`.
#[cfg(parallel_compiler)]
#[inline]
fn set_tlv<F: FnOnce() -> R, R>(value: usize, f: F) -> R {
rayon_core::tlv::with(value, f)
}

/// Gets Rayon's thread-local variable, which is preserved for Rayon jobs.
/// This is used to get the pointer to the current `ImplicitCtxt`.
#[cfg(parallel_compiler)]
#[inline]
pub fn get_tlv() -> usize {
rayon_core::tlv::get()
}

#[cfg(not(parallel_compiler))]
thread_local! {
/// A thread local variable that stores a pointer to the current `ImplicitCtxt`.
static TLV: Cell<usize> = const { Cell::new(0) };
}

/// Sets TLV 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`.
#[cfg(not(parallel_compiler))]
#[inline]
fn set_tlv<F: FnOnce() -> R, R>(value: usize, f: F) -> R {
let old = get_tlv();
let _reset = rustc_data_structures::OnDrop(move || TLV.with(|tlv| tlv.set(old)));
TLV.with(|tlv| tlv.set(value));
f()
}

/// Gets the pointer to the current `ImplicitCtxt`.
#[cfg(not(parallel_compiler))]
#[inline]
fn get_tlv() -> usize {
TLV.with(|tlv| tlv.get())
}

/// Sets `context` as the new current `ImplicitCtxt` for the duration of the function `f`.
#[inline]
pub fn enter_context<'a, 'tcx, F, R>(context: &ImplicitCtxt<'a, 'tcx>, f: F) -> R
Expand Down