From 9289d03c9d263ac32a9dd0a5c581779fe1def7d3 Mon Sep 17 00:00:00 2001 From: tyler Date: Wed, 15 May 2019 07:18:24 -0700 Subject: llvm makes good inlining choices with only the #[cold] attribute --- src/libstd/thread/local.rs | 34 +++++++++++++++------------------- 1 file changed, 15 insertions(+), 19 deletions(-) (limited to 'src/libstd/thread') diff --git a/src/libstd/thread/local.rs b/src/libstd/thread/local.rs index 1a12457646a..733c772a1f5 100644 --- a/src/libstd/thread/local.rs +++ b/src/libstd/thread/local.rs @@ -414,46 +414,42 @@ pub mod fast { } // `try_initialize` is only called once per fast thread local variable, - // except in corner cases where it is being recursively initialized. + // except in corner cases where thread_local dtors reference other + // thread_local's, or it is being recursively initialized. + // + // Macos: Inlining this function can cause two `tlv_get_addr` calls to + // be performed for every call to `Key::get`. The #[cold] hint makes + // that less likely. + // LLVM issue: https://bugs.llvm.org/show_bug.cgi?id=41722 #[cold] unsafe fn try_initialize T>(&self, init: F) -> Option<&'static T> { - if mem::needs_drop::() { - self.try_initialize_drop(init) - } else { + if !mem::needs_drop::() || self.try_register_dtor() { Some(self.inner.initialize(init)) + } else { + None } } - // `try_initialize_drop` is only called once per fast thread local + // `try_register_dtor` is only called once per fast thread local // variable, except in corner cases where thread_local dtors reference // other thread_local's, or it is being recursively initialized. - // - // Macos: Inlining this function causes two `tlv_get_addr` calls to be - // performed for every call to `Key::get`. - // LLVM issue: https://bugs.llvm.org/show_bug.cgi?id=41722 - #[inline(never)] - #[cold] - unsafe fn try_initialize_drop T>(&self, init: F) -> Option<&'static T> { - // We don't put a `needs_drop` check around this and call it a day - // because this function is not inlined. Unwrapping code gets - // generated for callers of `LocalKey::with` even if we always - // return `Some` here. + unsafe fn try_register_dtor(&self) -> bool { match self.dtor_state.get() { DtorState::Unregistered => { // dtor registration happens before initialization. register_dtor(self as *const _ as *mut u8, destroy_value::); self.dtor_state.set(DtorState::Registered); + true } DtorState::Registered => { // recursively initialized + true } DtorState::RunningOrHasRun => { - return None + false } } - - Some(self.inner.initialize(init)) } } -- cgit 1.4.1-3-g733a5