Skip to content

Commit 9f2c18a

Browse files
Auto merge of #143511 - orlp:tls-cold-init, r=<try>
Improve TLS codegen by marking the panic/init path as cold This is an extension of the performance improvements seen from <#141685>. I noticed that the non-`const` TLS still didn't have the `#[cold]` attribute for the uninit/panic path, and I also realized that neither implementation should have the initialization or panic path inlined, ever. These paths are taken either only once per thread (`init`) or never (`panic`, in a well-behaving Rust program), thus they don't deserve to litter the code generated each time you access a thread-local variable. So in addition to `#[cold]` I added the more aggressive `#[inline(never)]` to both cold paths as well.
2 parents 175e043 + db7b096 commit 9f2c18a

File tree

2 files changed

+18
-10
lines changed

2 files changed

+18
-10
lines changed

library/std/src/sys/thread_local/native/eager.rs

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use crate::sys::thread_local::{abort_on_dtor_unwind, destructors};
44

55
#[derive(Clone, Copy)]
66
enum State {
7-
Initial,
7+
Uninitialized,
88
Alive,
99
Destroyed,
1010
}
@@ -17,7 +17,7 @@ pub struct Storage<T> {
1717

1818
impl<T> Storage<T> {
1919
pub const fn new(val: T) -> Storage<T> {
20-
Storage { state: Cell::new(State::Initial), val: UnsafeCell::new(val) }
20+
Storage { state: Cell::new(State::Uninitialized), val: UnsafeCell::new(val) }
2121
}
2222

2323
/// Gets a pointer to the TLS value. If the TLS variable has been destroyed,
@@ -28,18 +28,25 @@ impl<T> Storage<T> {
2828
///
2929
/// # Safety
3030
/// The `self` reference must remain valid until the TLS destructor is run.
31-
#[inline]
31+
#[inline(always)]
3232
pub unsafe fn get(&self) -> *const T {
33-
match self.state.get() {
34-
State::Alive => self.val.get(),
35-
State::Destroyed => ptr::null(),
36-
State::Initial => unsafe { self.initialize() },
33+
if let State::Alive = self.state.get() {
34+
self.val.get()
35+
} else {
36+
unsafe { self.get_or_init_slow() }
3737
}
3838
}
3939

4040
#[cold]
41-
unsafe fn initialize(&self) -> *const T {
42-
// Register the destructor
41+
#[inline(never)]
42+
unsafe fn get_or_init_slow(&self) -> *const T {
43+
match self.state.get() {
44+
State::Uninitialized => {}
45+
State::Alive => return self.val.get(),
46+
State::Destroyed => return ptr::null(),
47+
}
48+
49+
// Register the destructor.
4350

4451
// SAFETY:
4552
// The caller guarantees that `self` will be valid until thread destruction.

library/std/src/sys/thread_local/native/lazy.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ where
5252
///
5353
/// # Safety
5454
/// The `self` reference must remain valid until the TLS destructor is run.
55-
#[inline]
55+
#[inline(always)]
5656
pub unsafe fn get_or_init(&self, i: Option<&mut Option<T>>, f: impl FnOnce() -> T) -> *const T {
5757
if let State::Alive = self.state.get() {
5858
self.value.get().cast()
@@ -64,6 +64,7 @@ where
6464
/// # Safety
6565
/// The `self` reference must remain valid until the TLS destructor is run.
6666
#[cold]
67+
#[inline(never)]
6768
unsafe fn get_or_init_slow(
6869
&self,
6970
i: Option<&mut Option<T>>,

0 commit comments

Comments
 (0)