mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-11 22:43:42 +00:00
Rollup merge of #122583 - Zoxc:tls-non-mut, r=joboet
Use `UnsafeCell` for fast constant thread locals This uses `UnsafeCell` instead of `static mut` for fast constant thread locals. This changes the type of the TLS shims to return `&UnsafeCell<T>` instead of `*mut T` which means they are always non-null so LLVM can optimize away the check for `Some` in `LocalKey::with` if `T` has no destructor. LLVM is currently unable to do this optimization as we lose the fact that `__getit` always returns `Some` as it gets optimized to just returning the value of the TLS shim.
This commit is contained in:
commit
a9f8f8b070
@ -13,22 +13,21 @@ pub macro thread_local_inner {
|
||||
(@key $t:ty, const $init:expr) => {{
|
||||
#[inline]
|
||||
#[deny(unsafe_op_in_unsafe_fn)]
|
||||
// FIXME: Use `SyncUnsafeCell` instead of allowing `static_mut_refs` lint
|
||||
#[cfg_attr(bootstrap, allow(static_mut_ref))]
|
||||
#[cfg_attr(not(bootstrap), allow(static_mut_refs))]
|
||||
unsafe fn __getit(
|
||||
_init: $crate::option::Option<&mut $crate::option::Option<$t>>,
|
||||
) -> $crate::option::Option<&'static $t> {
|
||||
const INIT_EXPR: $t = $init;
|
||||
// If the platform has support for `#[thread_local]`, use it.
|
||||
#[thread_local]
|
||||
static mut VAL: $t = INIT_EXPR;
|
||||
// We use `UnsafeCell` here instead of `static mut` to ensure any generated TLS shims
|
||||
// have a nonnull attribute on their return value.
|
||||
static VAL: $crate::cell::UnsafeCell<$t> = $crate::cell::UnsafeCell::new(INIT_EXPR);
|
||||
|
||||
// If a dtor isn't needed we can do something "very raw" and
|
||||
// just get going.
|
||||
if !$crate::mem::needs_drop::<$t>() {
|
||||
unsafe {
|
||||
return $crate::option::Option::Some(&VAL)
|
||||
return $crate::option::Option::Some(&*VAL.get())
|
||||
}
|
||||
}
|
||||
|
||||
@ -55,15 +54,15 @@ pub macro thread_local_inner {
|
||||
// so now.
|
||||
0 => {
|
||||
$crate::thread::local_impl::Key::<$t>::register_dtor(
|
||||
$crate::ptr::addr_of_mut!(VAL) as *mut $crate::primitive::u8,
|
||||
VAL.get() as *mut $crate::primitive::u8,
|
||||
destroy,
|
||||
);
|
||||
STATE.set(1);
|
||||
$crate::option::Option::Some(&VAL)
|
||||
$crate::option::Option::Some(&*VAL.get())
|
||||
}
|
||||
// 1 == the destructor is registered and the value
|
||||
// is valid, so return the pointer.
|
||||
1 => $crate::option::Option::Some(&VAL),
|
||||
1 => $crate::option::Option::Some(&*VAL.get()),
|
||||
// otherwise the destructor has already run, so we
|
||||
// can't give access.
|
||||
_ => $crate::option::Option::None,
|
||||
|
Loading…
Reference in New Issue
Block a user