Commit 1a48bcd9 authored by Andrew Gallagher's avatar Andrew Gallagher Committed by Facebook Github Bot

folly: fixes for use with `-fvisibility-inlines-hidden`

Summary:
- Annotate non-`const` static locals in inline functions which don't require
  a single copy be used globally at runtime.
- Move implmentation from header file to source file (to avoid multiple
  copies at runtime).
- Mark a non-stateful static local as `const` to it easy to ignore when
  searching for problematic static locals.

Reviewed By: yfeldblum

Differential Revision: D4010101

fbshipit-source-id: 3be94a5dc5b7029a26e11b2145c0d41968979a5c
parent b74eb888
...@@ -19,6 +19,20 @@ ...@@ -19,6 +19,20 @@
/* These definitions are in a separate file so that they /* These definitions are in a separate file so that they
* may be included from C- as well as C++-based projects. */ * may be included from C- as well as C++-based projects. */
/**
* Portable version check.
*/
#ifndef __GNUC_PREREQ
# if defined __GNUC__ && defined __GNUC_MINOR__
/* nolint */
# define __GNUC_PREREQ(maj, min) ((__GNUC__ << 16) + __GNUC_MINOR__ >= \
((maj) << 16) + (min))
# else
/* nolint */
# define __GNUC_PREREQ(maj, min) 0
# endif
#endif
/* Define a convenience macro to test when address sanitizer is being used /* Define a convenience macro to test when address sanitizer is being used
* across the different compilers (e.g. clang, gcc) */ * across the different compilers (e.g. clang, gcc) */
#if defined(__clang__) #if defined(__clang__)
...@@ -80,3 +94,16 @@ ...@@ -80,3 +94,16 @@
#else #else
# define UBSAN_DISABLE(x) # define UBSAN_DISABLE(x)
#endif // UNDEFINED_SANITIZER #endif // UNDEFINED_SANITIZER
/**
* Macro for marking functions as having public visibility.
*/
#if defined(__GNUC__)
# if __GNUC_PREREQ(4, 9)
# define FOLLY_EXPORT [[gnu::visibility("default")]]
# else
# define FOLLY_EXPORT __attribute__((__visibility__("default")))
# endif
#else
# define FOLLY_EXPORT
#endif
...@@ -179,7 +179,7 @@ FOLLY_MALLOC_NOINLINE inline bool usingJEMalloc() noexcept { ...@@ -179,7 +179,7 @@ FOLLY_MALLOC_NOINLINE inline bool usingJEMalloc() noexcept {
// Static because otherwise clever compilers will find out that // Static because otherwise clever compilers will find out that
// the ptr is not used and does not escape the scope, so they will // the ptr is not used and does not escape the scope, so they will
// just optimize away the malloc. // just optimize away the malloc.
static void* ptr = malloc(1); static const void* ptr = malloc(1);
if (!ptr) { if (!ptr) {
// wtf, failing to allocate 1 byte // wtf, failing to allocate 1 byte
return false; return false;
......
...@@ -167,18 +167,6 @@ constexpr bool kHasUnalignedAccess = false; ...@@ -167,18 +167,6 @@ constexpr bool kHasUnalignedAccess = false;
# define FOLLY_MSVC_DISABLE_WARNING(warningNumber) # define FOLLY_MSVC_DISABLE_WARNING(warningNumber)
#endif #endif
// portable version check
#ifndef __GNUC_PREREQ
# if defined __GNUC__ && defined __GNUC_MINOR__
/* nolint */
# define __GNUC_PREREQ(maj, min) ((__GNUC__ << 16) + __GNUC_MINOR__ >= \
((maj) << 16) + (min))
# else
/* nolint */
# define __GNUC_PREREQ(maj, min) 0
# endif
#endif
#if defined(__GNUC__) && !defined(__APPLE__) && !__GNUC_PREREQ(4,9) #if defined(__GNUC__) && !defined(__APPLE__) && !__GNUC_PREREQ(4,9)
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56019 // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56019
// gcc 4.8.x incorrectly placed max_align_t in the root namespace // gcc 4.8.x incorrectly placed max_align_t in the root namespace
......
...@@ -21,7 +21,7 @@ namespace detail { ...@@ -21,7 +21,7 @@ namespace detail {
template <typename T> template <typename T>
template <typename Tag, typename VaultTag> template <typename Tag, typename VaultTag>
SingletonHolder<T>& SingletonHolder<T>::singleton() { SingletonHolder<T>& SingletonHolder<T>::singleton() {
static auto entry = /* library-local */ static auto entry =
createGlobal<SingletonHolder<T>, std::pair<Tag, VaultTag>>([]() { createGlobal<SingletonHolder<T>, std::pair<Tag, VaultTag>>([]() {
return new SingletonHolder<T>({typeid(T), typeid(Tag)}, return new SingletonHolder<T>({typeid(T), typeid(Tag)},
*SingletonVault::singleton<VaultTag>()); *SingletonVault::singleton<VaultTag>());
......
...@@ -434,7 +434,7 @@ class SingletonVault { ...@@ -434,7 +434,7 @@ class SingletonVault {
// tests only. // tests only.
template <typename VaultTag = detail::DefaultTag> template <typename VaultTag = detail::DefaultTag>
static SingletonVault* singleton() { static SingletonVault* singleton() {
static SingletonVault* vault = /* library-local */ static auto vault =
detail::createGlobal<SingletonVault, VaultTag>(); detail::createGlobal<SingletonVault, VaultTag>();
return vault; return vault;
} }
...@@ -442,9 +442,8 @@ class SingletonVault { ...@@ -442,9 +442,8 @@ class SingletonVault {
typedef std::string(*StackTraceGetterPtr)(); typedef std::string(*StackTraceGetterPtr)();
static std::atomic<StackTraceGetterPtr>& stackTraceGetter() { static std::atomic<StackTraceGetterPtr>& stackTraceGetter() {
static std::atomic<StackTraceGetterPtr>* stackTraceGetterPtr = /* library-local */ static auto stackTraceGetterPtr = detail::
detail::createGlobal<std::atomic<StackTraceGetterPtr>, createGlobal<std::atomic<StackTraceGetterPtr>, SingletonVault>();
SingletonVault>();
return *stackTraceGetterPtr; return *stackTraceGetterPtr;
} }
...@@ -657,7 +656,7 @@ class LeakySingleton { ...@@ -657,7 +656,7 @@ class LeakySingleton {
}; };
static Entry& entryInstance() { static Entry& entryInstance() {
static auto entry = detail::createGlobal<Entry, Tag>(); /* library-local */ static auto entry = detail::createGlobal<Entry, Tag>();
return *entry; return *entry;
} }
......
...@@ -325,7 +325,7 @@ struct StaticMeta : StaticMetaBase { ...@@ -325,7 +325,7 @@ struct StaticMeta : StaticMetaBase {
static StaticMeta<Tag, AccessMode>& instance() { static StaticMeta<Tag, AccessMode>& instance() {
// Leak it on exit, there's only one per process and we don't have to // Leak it on exit, there's only one per process and we don't have to
// worry about synchronization with exiting threads. // worry about synchronization with exiting threads.
static auto instance = /* library-local */ static auto instance =
detail::createGlobal<StaticMeta<Tag, AccessMode>, void>(); detail::createGlobal<StaticMeta<Tag, AccessMode>, void>();
return *instance; return *instance;
} }
......
...@@ -112,4 +112,13 @@ std::shared_ptr<RequestContext>& RequestContext::getStaticContext() { ...@@ -112,4 +112,13 @@ std::shared_ptr<RequestContext>& RequestContext::getStaticContext() {
return singleton.get(); return singleton.get();
} }
RequestContext* RequestContext::get() {
auto context = getStaticContext();
if (!context) {
static RequestContext defaultContext;
return std::addressof(defaultContext);
}
return context.get();
}
} }
...@@ -53,14 +53,7 @@ class RequestContext { ...@@ -53,14 +53,7 @@ class RequestContext {
} }
// Get the current context. // Get the current context.
static RequestContext* get() { static RequestContext* get();
auto context = getStaticContext();
if (!context) {
static RequestContext defaultContext;
return std::addressof(defaultContext);
}
return context.get();
}
// The following API may be used to set per-request data in a thread-safe way. // The following API may be used to set per-request data in a thread-safe way.
// This access is still performance sensitive, so please ask if you need help // This access is still performance sensitive, so please ask if you need help
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment