Commit 22ec7dc9 by James Darpinian Committed by Commit Bot

Remove all global constructors and exit time destructors.

WebKit compiles with -Wglobal-constructors, so they want this. I decided to do -Wexit-time-destructors at the same time. Bug: angleproject:3439 Bug: angleproject:1459 Change-Id: I4b44ae4f8e6f066e07dc7f9f6ced9a5d49dc8f8a Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1738438 Commit-Queue: James Darpinian <jdarpinian@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 7c7dec01
...@@ -129,6 +129,8 @@ config("extra_warnings") { ...@@ -129,6 +129,8 @@ config("extra_warnings") {
"-Wfloat-conversion", "-Wfloat-conversion",
"-Wnon-virtual-dtor", "-Wnon-virtual-dtor",
"-Wunneeded-internal-declaration", "-Wunneeded-internal-declaration",
"-Wglobal-constructors",
"-Wexit-time-destructors",
] ]
} }
} }
...@@ -932,6 +934,7 @@ angle_shared_library("libEGL") { ...@@ -932,6 +934,7 @@ angle_shared_library("libEGL") {
} }
deps = [ deps = [
":angle_common",
":angle_system_utils", ":angle_system_utils",
":angle_version", ":angle_version",
":libEGL_egl_loader", ":libEGL_egl_loader",
...@@ -1074,6 +1077,7 @@ foreach(is_shared_library, ...@@ -1074,6 +1077,7 @@ foreach(is_shared_library,
} }
configs += [ ":debug_annotations_config" ] configs += [ ":debug_annotations_config" ]
configs -= [ "${angle_root}:extra_warnings" ]
public_configs += [ ":angle_util_config" ] public_configs += [ ":angle_util_config" ]
......
...@@ -237,6 +237,7 @@ template("angle_test") { ...@@ -237,6 +237,7 @@ template("angle_test") {
configs += invoker.configs configs += invoker.configs
configs -= invoker.suppressed_configs configs -= invoker.suppressed_configs
configs -= [ angle_root + ":extra_warnings" ]
if (is_linux && !is_component_build) { if (is_linux && !is_component_build) {
# Set rpath to find shared libs in a non-component build. # Set rpath to find shared libs in a non-component build.
......
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef ANGLEBASE_NO_DESTRUCTOR_H_
#define ANGLEBASE_NO_DESTRUCTOR_H_
#include <new>
#include <utility>
namespace angle
{
namespace base
{
// A wrapper that makes it easy to create an object of type T with static
// storage duration that:
// - is only constructed on first access
// - never invokes the destructor
// in order to satisfy the styleguide ban on global constructors and
// destructors.
//
// Runtime constant example:
// const std::string& GetLineSeparator() {
// // Forwards to std::string(size_t, char, const Allocator&) constructor.
// static const base::NoDestructor<std::string> s(5, '-');
// return *s;
// }
//
// More complex initialization with a lambda:
// const std::string& GetSessionNonce() {
// static const base::NoDestructor<std::string> nonce([] {
// std::string s(16);
// crypto::RandString(s.data(), s.size());
// return s;
// }());
// return *nonce;
// }
//
// NoDestructor<T> stores the object inline, so it also avoids a pointer
// indirection and a malloc. Also note that since C++11 static local variable
// initialization is thread-safe and so is this pattern. Code should prefer to
// use NoDestructor<T> over:
// - A function scoped static T* or T& that is dynamically initialized.
// - A global base::LazyInstance<T>.
//
// Note that since the destructor is never run, this *will* leak memory if used
// as a stack or member variable. Furthermore, a NoDestructor<T> should never
// have global scope as that may require a static initializer.
template <typename T>
class NoDestructor
{
public:
// Not constexpr; just write static constexpr T x = ...; if the value should
// be a constexpr.
template <typename... Args>
explicit NoDestructor(Args &&... args)
{
new (storage_) T(std::forward<Args>(args)...);
}
// Allows copy and move construction of the contained type, to allow
// construction from an initializer list, e.g. for std::vector.
explicit NoDestructor(const T &x) { new (storage_) T(x); }
explicit NoDestructor(T &&x) { new (storage_) T(std::move(x)); }
NoDestructor(const NoDestructor &) = delete;
NoDestructor &operator=(const NoDestructor &) = delete;
~NoDestructor() = default;
const T &operator*() const { return *get(); }
T &operator*() { return *get(); }
const T *operator->() const { return get(); }
T *operator->() { return get(); }
const T *get() const { return reinterpret_cast<const T *>(storage_); }
T *get() { return reinterpret_cast<T *>(storage_); }
private:
alignas(T) char storage_[sizeof(T)];
#if defined(LEAK_SANITIZER)
// TODO(https://crbug.com/812277): This is a hack to work around the fact
// that LSan doesn't seem to treat NoDestructor as a root for reachability
// analysis. This means that code like this:
// static base::NoDestructor<std::vector<int>> v({1, 2, 3});
// is considered a leak. Using the standard leak sanitizer annotations to
// suppress leaks doesn't work: std::vector is implicitly constructed before
// calling the base::NoDestructor constructor.
//
// Unfortunately, I haven't been able to demonstrate this issue in simpler
// reproductions: until that's resolved, hold an explicit pointer to the
// placement-new'd object in leak sanitizer mode to help LSan realize that
// objects allocated by the contained type are still reachable.
T *storage_ptr_ = reinterpret_cast<T *>(storage_);
#endif // defined(LEAK_SANITIZER)
};
} // namespace base
} // namespace angle
#endif // ANGLEBASE_NO_DESTRUCTOR_H_
\ No newline at end of file
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include <unordered_map> #include <unordered_map>
#include "angle_gl.h" #include "angle_gl.h"
#include "anglebase/no_destructor.h"
#include "compiler/translator/Compiler.h" #include "compiler/translator/Compiler.h"
#include "compiler/translator/util.h" #include "compiler/translator/util.h"
...@@ -49,10 +50,6 @@ struct TCompilerDeleter ...@@ -49,10 +50,6 @@ struct TCompilerDeleter
void operator()(TCompiler *compiler) const { DeleteCompiler(compiler); } void operator()(TCompiler *compiler) const { DeleteCompiler(compiler); }
}; };
using UniqueTCompiler = std::unique_ptr<TCompiler, TCompilerDeleter>;
static std::unordered_map<TranslatorCacheKey, UniqueTCompiler> translators;
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
{ {
// Reserve some size for future compile options // Reserve some size for future compile options
...@@ -132,7 +129,11 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) ...@@ -132,7 +129,11 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
key.spec = spec; key.spec = spec;
key.output = output; key.output = output;
if (translators.find(key) == translators.end()) using UniqueTCompiler = std::unique_ptr<TCompiler, TCompilerDeleter>;
static angle::base::NoDestructor<std::unordered_map<TranslatorCacheKey, UniqueTCompiler>>
translators;
if (translators->find(key) == translators->end())
{ {
UniqueTCompiler translator( UniqueTCompiler translator(
ConstructCompiler(type, static_cast<ShShaderSpec>(spec), shaderOutput)); ConstructCompiler(type, static_cast<ShShaderSpec>(spec), shaderOutput));
...@@ -167,10 +168,10 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) ...@@ -167,10 +168,10 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
return 0; return 0;
} }
translators[key] = std::move(translator); (*translators)[key] = std::move(translator);
} }
auto &translator = translators[key]; auto &translator = (*translators)[key];
const char *shaderStrings[] = {reinterpret_cast<const char *>(data)}; const char *shaderStrings[] = {reinterpret_cast<const char *>(data)};
translator->compile(shaderStrings, 1, options); translator->compile(shaderStrings, 1, options);
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#include "libANGLE/Caps.h" #include "libANGLE/Caps.h"
#include "anglebase/no_destructor.h"
#include "common/angleutils.h" #include "common/angleutils.h"
#include "common/debug.h" #include "common/debug.h"
...@@ -849,8 +850,8 @@ const ExtensionInfoMap &GetExtensionInfoMap() ...@@ -849,8 +850,8 @@ const ExtensionInfoMap &GetExtensionInfoMap()
return map; return map;
}; };
static const ExtensionInfoMap extensionInfo = buildExtensionInfoMap(); static const angle::base::NoDestructor<ExtensionInfoMap> extensionInfo(buildExtensionInfoMap());
return extensionInfo; return *extensionInfo;
} }
TypePrecision::TypePrecision() = default; TypePrecision::TypePrecision() = default;
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include <EGL/eglext.h> #include <EGL/eglext.h>
#include <platform/Platform.h> #include <platform/Platform.h>
#include "anglebase/no_destructor.h"
#include "common/debug.h" #include "common/debug.h"
#include "common/platform.h" #include "common/platform.h"
#include "libANGLE/renderer/DeviceImpl.h" #include "libANGLE/renderer/DeviceImpl.h"
...@@ -39,8 +40,8 @@ static std::string GenerateExtensionsString(const T &extensions) ...@@ -39,8 +40,8 @@ static std::string GenerateExtensionsString(const T &extensions)
typedef std::set<egl::Device *> DeviceSet; typedef std::set<egl::Device *> DeviceSet;
static DeviceSet *GetDeviceSet() static DeviceSet *GetDeviceSet()
{ {
static DeviceSet devices; static angle::base::NoDestructor<DeviceSet> devices;
return &devices; return devices.get();
} }
// Static factory methods // Static factory methods
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include <EGL/eglext.h> #include <EGL/eglext.h>
#include <platform/Platform.h> #include <platform/Platform.h>
#include "anglebase/no_destructor.h"
#include "common/android_util.h" #include "common/android_util.h"
#include "common/debug.h" #include "common/debug.h"
#include "common/mathutil.h" #include "common/mathutil.h"
...@@ -89,22 +90,22 @@ typedef std::map<EGLNativeWindowType, Surface *> WindowSurfaceMap; ...@@ -89,22 +90,22 @@ typedef std::map<EGLNativeWindowType, Surface *> WindowSurfaceMap;
// associated with it. // associated with it.
static WindowSurfaceMap *GetWindowSurfaces() static WindowSurfaceMap *GetWindowSurfaces()
{ {
static WindowSurfaceMap windowSurfaces; static angle::base::NoDestructor<WindowSurfaceMap> windowSurfaces;
return &windowSurfaces; return windowSurfaces.get();
} }
typedef std::map<EGLNativeDisplayType, Display *> ANGLEPlatformDisplayMap; typedef std::map<EGLNativeDisplayType, Display *> ANGLEPlatformDisplayMap;
static ANGLEPlatformDisplayMap *GetANGLEPlatformDisplayMap() static ANGLEPlatformDisplayMap *GetANGLEPlatformDisplayMap()
{ {
static ANGLEPlatformDisplayMap displays; static angle::base::NoDestructor<ANGLEPlatformDisplayMap> displays;
return &displays; return displays.get();
} }
typedef std::map<Device *, Display *> DevicePlatformDisplayMap; typedef std::map<Device *, Display *> DevicePlatformDisplayMap;
static DevicePlatformDisplayMap *GetDevicePlatformDisplayMap() static DevicePlatformDisplayMap *GetDevicePlatformDisplayMap()
{ {
static DevicePlatformDisplayMap displays; static angle::base::NoDestructor<DevicePlatformDisplayMap> displays;
return &displays; return displays.get();
} }
rx::DisplayImpl *CreateDisplayFromDevice(Device *eglDevice, const DisplayState &state) rx::DisplayImpl *CreateDisplayFromDevice(Device *eglDevice, const DisplayState &state)
...@@ -1266,9 +1267,9 @@ const ClientExtensions &Display::GetClientExtensions() ...@@ -1266,9 +1267,9 @@ const ClientExtensions &Display::GetClientExtensions()
// static // static
const std::string &Display::GetClientExtensionString() const std::string &Display::GetClientExtensionString()
{ {
static const std::string clientExtensionsString = static const angle::base::NoDestructor<std::string> clientExtensionsString(
GenerateExtensionsString(GetClientExtensions()); GenerateExtensionsString(GetClientExtensions()));
return clientExtensionsString; return *clientExtensionsString;
} }
void Display::initDisplayExtensions() void Display::initDisplayExtensions()
......
...@@ -15,12 +15,16 @@ ...@@ -15,12 +15,16 @@
namespace namespace
{ {
// TODO(jmadill): Make methods owned by egl::Display. // TODO(jmadill): Make methods owned by egl::Display.
angle::PlatformMethods g_platformMethods; angle::PlatformMethods &PlatformMethods()
{
static angle::PlatformMethods platformMethods;
return platformMethods;
}
} // anonymous namespace } // anonymous namespace
angle::PlatformMethods *ANGLEPlatformCurrent() angle::PlatformMethods *ANGLEPlatformCurrent()
{ {
return &g_platformMethods; return &PlatformMethods();
} }
bool ANGLE_APIENTRY ANGLEGetDisplayPlatform(angle::EGLDisplayType display, bool ANGLE_APIENTRY ANGLEGetDisplayPlatform(angle::EGLDisplayType display,
...@@ -53,13 +57,13 @@ bool ANGLE_APIENTRY ANGLEGetDisplayPlatform(angle::EGLDisplayType display, ...@@ -53,13 +57,13 @@ bool ANGLE_APIENTRY ANGLEGetDisplayPlatform(angle::EGLDisplayType display,
} }
// TODO(jmadill): Store platform methods in display. // TODO(jmadill): Store platform methods in display.
g_platformMethods.context = context; PlatformMethods().context = context;
*platformMethodsOut = &g_platformMethods; *platformMethodsOut = &PlatformMethods();
return true; return true;
} }
void ANGLE_APIENTRY ANGLEResetDisplayPlatform(angle::EGLDisplayType display) void ANGLE_APIENTRY ANGLEResetDisplayPlatform(angle::EGLDisplayType display)
{ {
// TODO(jmadill): Store platform methods in display. // TODO(jmadill): Store platform methods in display.
g_platformMethods = angle::PlatformMethods(); PlatformMethods() = angle::PlatformMethods();
} }
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include "libANGLE/formatutils.h" #include "libANGLE/formatutils.h"
#include "anglebase/no_destructor.h"
#include "common/mathutil.h" #include "common/mathutil.h"
#include "libANGLE/Context.h" #include "libANGLE/Context.h"
#include "libANGLE/Framebuffer.h" #include "libANGLE/Framebuffer.h"
...@@ -1038,8 +1039,9 @@ static InternalFormatInfoMap BuildInternalFormatInfoMap() ...@@ -1038,8 +1039,9 @@ static InternalFormatInfoMap BuildInternalFormatInfoMap()
static const InternalFormatInfoMap &GetInternalFormatMap() static const InternalFormatInfoMap &GetInternalFormatMap()
{ {
static const InternalFormatInfoMap formatMap = BuildInternalFormatInfoMap(); static const angle::base::NoDestructor<InternalFormatInfoMap> formatMap(
return formatMap; BuildInternalFormatInfoMap());
return *formatMap;
} }
static FormatSet BuildAllSizedInternalFormatSet() static FormatSet BuildAllSizedInternalFormatSet()
...@@ -1328,8 +1330,8 @@ GLenum GetUnsizedFormat(GLenum internalFormat) ...@@ -1328,8 +1330,8 @@ GLenum GetUnsizedFormat(GLenum internalFormat)
const FormatSet &GetAllSizedInternalFormats() const FormatSet &GetAllSizedInternalFormats()
{ {
static FormatSet formatSet = BuildAllSizedInternalFormatSet(); static angle::base::NoDestructor<FormatSet> formatSet(BuildAllSizedInternalFormatSet());
return formatSet; return *formatSet;
} }
AttributeType GetAttributeType(GLenum enumValue) AttributeType GetAttributeType(GLenum enumValue)
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include "image_util/generatemip.h" #include "image_util/generatemip.h"
#include "image_util/loadimage.h" #include "image_util/loadimage.h"
#include "anglebase/no_destructor.h"
#include "libANGLE/renderer/d3d/d3d9/Renderer9.h" #include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
#include "libANGLE/renderer/d3d/d3d9/vertexconversion.h" #include "libANGLE/renderer/d3d/d3d9/vertexconversion.h"
...@@ -265,12 +266,12 @@ static inline void InsertD3D9FormatInfo(D3D9FormatMap *map, ...@@ -265,12 +266,12 @@ static inline void InsertD3D9FormatInfo(D3D9FormatMap *map,
info.texFormat = texFormat; info.texFormat = texFormat;
info.renderFormat = renderFormat; info.renderFormat = renderFormat;
static const InternalFormatInitialzerMap dataInitializationMap = static const angle::base::NoDestructor<InternalFormatInitialzerMap> dataInitializationMap(
BuildInternalFormatInitialzerMap(); BuildInternalFormatInitialzerMap());
InternalFormatInitialzerMap::const_iterator dataInitIter = InternalFormatInitialzerMap::const_iterator dataInitIter =
dataInitializationMap.find(internalFormat); dataInitializationMap->find(internalFormat);
info.dataInitializerFunction = info.dataInitializerFunction =
(dataInitIter != dataInitializationMap.end()) ? dataInitIter->second : nullptr; (dataInitIter != dataInitializationMap->end()) ? dataInitIter->second : nullptr;
info.loadFunction = loadFunction; info.loadFunction = loadFunction;
...@@ -347,9 +348,9 @@ static D3D9FormatMap BuildD3D9FormatMap() ...@@ -347,9 +348,9 @@ static D3D9FormatMap BuildD3D9FormatMap()
const TextureFormat &GetTextureFormatInfo(GLenum internalFormat) const TextureFormat &GetTextureFormatInfo(GLenum internalFormat)
{ {
static const D3D9FormatMap formatMap = BuildD3D9FormatMap(); static const angle::base::NoDestructor<D3D9FormatMap> formatMap(BuildD3D9FormatMap());
D3D9FormatMap::const_iterator iter = formatMap.find(internalFormat); D3D9FormatMap::const_iterator iter = formatMap->find(internalFormat);
if (iter != formatMap.end()) if (iter != formatMap->end())
{ {
return iter->second; return iter->second;
} }
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include <limits> #include <limits>
#include "anglebase/no_destructor.h"
#include "common/string_utils.h" #include "common/string_utils.h"
#include "libANGLE/formatutils.h" #include "libANGLE/formatutils.h"
#include "platform/FeaturesGL.h" #include "platform/FeaturesGL.h"
...@@ -367,8 +368,9 @@ static InternalFormatInfoMap BuildInternalFormatInfoMap() ...@@ -367,8 +368,9 @@ static InternalFormatInfoMap BuildInternalFormatInfoMap()
static const InternalFormatInfoMap &GetInternalFormatMap() static const InternalFormatInfoMap &GetInternalFormatMap()
{ {
static const InternalFormatInfoMap formatMap = BuildInternalFormatInfoMap(); static const angle::base::NoDestructor<InternalFormatInfoMap> formatMap(
return formatMap; BuildInternalFormatInfoMap());
return *formatMap;
} }
const InternalFormat &GetInternalFormatInfo(GLenum internalFormat, StandardGL standard) const InternalFormat &GetInternalFormatInfo(GLenum internalFormat, StandardGL standard)
...@@ -390,8 +392,8 @@ const InternalFormat &GetInternalFormatInfo(GLenum internalFormat, StandardGL st ...@@ -390,8 +392,8 @@ const InternalFormat &GetInternalFormatInfo(GLenum internalFormat, StandardGL st
} }
} }
static const InternalFormat defaultInternalFormat; static const angle::base::NoDestructor<InternalFormat> defaultInternalFormat;
return defaultInternalFormat; return *defaultInternalFormat;
} }
static GLenum GetNativeInternalFormat(const FunctionsGL *functions, static GLenum GetNativeInternalFormat(const FunctionsGL *functions,
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
// libEGL.cpp: Implements the exported EGL functions. // libEGL.cpp: Implements the exported EGL functions.
#include "anglebase/no_destructor.h"
#include "common/system_utils.h" #include "common/system_utils.h"
#include <memory> #include <memory>
...@@ -21,11 +22,16 @@ namespace ...@@ -21,11 +22,16 @@ namespace
{ {
#if defined(ANGLE_USE_EGL_LOADER) #if defined(ANGLE_USE_EGL_LOADER)
bool gLoaded = false; bool gLoaded = false;
std::unique_ptr<angle::Library> gEntryPointsLib;
std::unique_ptr<angle::Library> &EntryPointsLib()
{
static angle::base::NoDestructor<std::unique_ptr<angle::Library>> entryPointsLib;
return *entryPointsLib;
}
angle::GenericProc KHRONOS_APIENTRY GlobalLoad(const char *symbol) angle::GenericProc KHRONOS_APIENTRY GlobalLoad(const char *symbol)
{ {
return reinterpret_cast<angle::GenericProc>(gEntryPointsLib->getSymbol(symbol)); return reinterpret_cast<angle::GenericProc>(EntryPointsLib()->getSymbol(symbol));
} }
void EnsureEGLLoaded() void EnsureEGLLoaded()
...@@ -33,7 +39,7 @@ void EnsureEGLLoaded() ...@@ -33,7 +39,7 @@ void EnsureEGLLoaded()
if (gLoaded) if (gLoaded)
return; return;
gEntryPointsLib.reset( EntryPointsLib().reset(
angle::OpenSharedLibrary(ANGLE_GLESV2_LIBRARY_NAME, angle::SearchType::ApplicationDir)); angle::OpenSharedLibrary(ANGLE_GLESV2_LIBRARY_NAME, angle::SearchType::ApplicationDir));
angle::LoadEGL_EGL(GlobalLoad); angle::LoadEGL_EGL(GlobalLoad);
if (!EGL_GetPlatformDisplay) if (!EGL_GetPlatformDisplay)
......
...@@ -42,6 +42,7 @@ libangle_common_sources = [ ...@@ -42,6 +42,7 @@ libangle_common_sources = [
"src/common/third_party/base/anglebase/containers/mru_cache.h", "src/common/third_party/base/anglebase/containers/mru_cache.h",
"src/common/third_party/base/anglebase/logging.h", "src/common/third_party/base/anglebase/logging.h",
"src/common/third_party/base/anglebase/macros.h", "src/common/third_party/base/anglebase/macros.h",
"src/common/third_party/base/anglebase/no_destructor.h",
"src/common/third_party/base/anglebase/numerics/safe_conversions.h", "src/common/third_party/base/anglebase/numerics/safe_conversions.h",
"src/common/third_party/base/anglebase/numerics/safe_conversions_impl.h", "src/common/third_party/base/anglebase/numerics/safe_conversions_impl.h",
"src/common/third_party/base/anglebase/numerics/safe_math.h", "src/common/third_party/base/anglebase/numerics/safe_math.h",
......
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