diff --git a/src/base/low_level_alloc.cc b/src/base/low_level_alloc.cc index f40b0bd..e762d7d 100644 --- a/src/base/low_level_alloc.cc +++ b/src/base/low_level_alloc.cc @@ -37,8 +37,9 @@ #include "base/low_level_alloc.h" #include "base/dynamic_annotations.h" -#include "base/spinlock.h" #include "base/logging.h" +#include "base/spinlock.h" +#include "base/static_storage.h" #include "malloc_hook-inl.h" #include @@ -524,18 +525,14 @@ LowLevelAlloc::Arena *LowLevelAlloc::DefaultArena() { return &default_arena; } -static DefaultPagesAllocator *default_pages_allocator; -static union { - char chars[sizeof(DefaultPagesAllocator)]; - void *ptr; -} debug_pages_allocator_space; +static tcmalloc::StaticStorage default_pages_allocator; LowLevelAlloc::PagesAllocator *LowLevelAlloc::GetDefaultPagesAllocator(void) { - if (default_pages_allocator) { - return default_pages_allocator; - } - default_pages_allocator = new (debug_pages_allocator_space.chars) DefaultPagesAllocator(); - return default_pages_allocator; + static tcmalloc::TrivialOnce once; + once.RunOnce(+[] () { + default_pages_allocator.Construct(); + }); + return default_pages_allocator.get(); } void *DefaultPagesAllocator::MapPages(int32_t flags, size_t size) { diff --git a/src/debugallocation.cc b/src/debugallocation.cc index 395db1b..7150177 100644 --- a/src/debugallocation.cc +++ b/src/debugallocation.cc @@ -71,6 +71,7 @@ #include "base/googleinit.h" #include "base/logging.h" #include "base/spinlock.h" +#include "base/static_storage.h" #include "base/threading.h" #include "malloc_hook-inl.h" #include "maybe_emergency_malloc.h" @@ -697,9 +698,9 @@ class MallocBlock { // We don't want to allocate or deallocate memory here, so we use // placement-new. It's ok that we don't destroy this, since we're - // just going to error-exit below anyway. Union is for alignment. - union { void* alignment; char buf[sizeof(SymbolTable)]; } tablebuf; - SymbolTable* symbolization_table = new (tablebuf.buf) SymbolTable; + // just going to error-exit below anyway. + tcmalloc::StaticStorage tablebuf; + SymbolTable* symbolization_table = tablebuf.Construct(); for (int i = 0; i < queue_entry.num_deleter_pcs; i++) { // Symbolizes the previous address of pc because pc may be in the // next function. This may happen when the function ends with @@ -1071,10 +1072,8 @@ class DebugMallocImplementation : public TCMallocImplementation { virtual bool GetNumericProperty(const char* name, size_t* value) { if (TestingPortal** portal = TestingPortal::CheckGetPortal(name, value); portal) { static DebugTestingPortal* ptr = ([] () { - static struct { - alignas(DebugTestingPortal) char memory[sizeof(DebugTestingPortal)]; - } storage; - return new (storage.memory) DebugTestingPortal; + static tcmalloc::StaticStorage storage; + return storage.Construct(); })(); *portal = ptr; *value = 1; @@ -1177,11 +1176,10 @@ class DebugMallocImplementation : public TCMallocImplementation { }; +static tcmalloc::StaticStorage debug_malloc_impl_storage; + void SetupMallocExtension() { - static struct { - alignas(DebugMallocImplementation) char memory[sizeof(DebugMallocImplementation)]; - } storage; - MallocExtension::Register(new (storage.memory) DebugMallocImplementation); + MallocExtension::Register(debug_malloc_impl_storage.Construct()); } REGISTER_MODULE_DESTRUCTOR(debugallocation, { diff --git a/src/memfs_malloc.cc b/src/memfs_malloc.cc index 0c7acbc..b536c9b 100644 --- a/src/memfs_malloc.cc +++ b/src/memfs_malloc.cc @@ -56,6 +56,7 @@ #include #include "base/basictypes.h" #include "base/googleinit.h" +#include "base/static_storage.h" #include "base/sysinfo.h" #include "internal_logging.h" #include "safe_strerror.h" @@ -114,10 +115,7 @@ private: SysAllocator* fallback_; // Default system allocator to fall back to. }; -static union { - char buf[sizeof(HugetlbSysAllocator)]; - void *ptr; -} hugetlb_space; +static tcmalloc::StaticStorage hugetlb_space; // No locking needed here since we assume that tcmalloc calls // us with an internal lock held (see tcmalloc/system-alloc.cc). @@ -270,8 +268,7 @@ bool HugetlbSysAllocator::Initialize() { REGISTER_MODULE_INITIALIZER(memfs_malloc, { if (FLAGS_memfs_malloc_path.length()) { SysAllocator* alloc = MallocExtension::instance()->GetSystemAllocator(); - HugetlbSysAllocator* hp = - new (hugetlb_space.buf) HugetlbSysAllocator(alloc); + HugetlbSysAllocator* hp = hugetlb_space.Construct(alloc); if (hp->Initialize()) { MallocExtension::instance()->SetSystemAllocator(hp); } diff --git a/src/memory_region_map.cc b/src/memory_region_map.cc index 179ed6b..3971bab 100644 --- a/src/memory_region_map.cc +++ b/src/memory_region_map.cc @@ -163,20 +163,6 @@ static inline bool current_thread_is(std::thread::id should_be) { // ========================================================================= // -// Constructor-less place-holder to store a RegionSet in. -union MemoryRegionMap::RegionSetRep { - char rep[sizeof(RegionSet)]; - void* align_it; // do not need a better alignment for 'rep' than this - RegionSet* region_set() { return reinterpret_cast(rep); } -}; - -// The bytes where MemoryRegionMap::regions_ will point to. -// We use RegionSetRep with noop c-tor so that global construction -// does not interfere. -static MemoryRegionMap::RegionSetRep regions_rep; - -// ========================================================================= // - // Has InsertRegionLocked been called recursively // (or rather should we *not* use regions_ to record a hooked mmap). static bool recursive_insert = false; @@ -527,7 +513,7 @@ void MemoryRegionMap::RestoreSavedBucketsLocked() { inline void MemoryRegionMap::InitRegionSetLocked() { RAW_VLOG(12, "Initializing region set"); - regions_ = regions_rep.region_set(); + regions_ = regions_rep_.get(); recursive_insert = true; new (regions_) RegionSet(); HandleSavedRegionsLocked(&DoInsertRegionLocked); diff --git a/src/memory_region_map.h b/src/memory_region_map.h index c252c28..5928ab9 100644 --- a/src/memory_region_map.h +++ b/src/memory_region_map.h @@ -257,6 +257,11 @@ class MemoryRegionMap { typedef std::set > RegionSet; + // The bytes where MemoryRegionMap::regions_ will point to. We use + // StaticStorage with noop c-tor so that global construction does + // not interfere. + static inline tcmalloc::StaticStorage regions_rep_; + public: // more in-depth interface ========================================== // STL iterator with values of Region @@ -275,11 +280,6 @@ class MemoryRegionMap { // Return the accumulated sizes of mapped and unmapped regions. static int64_t MapSize() { return map_size_; } static int64_t UnmapSize() { return unmap_size_; } - - // Effectively private type from our .cc ================================= - // public to let us declare global objects: - union RegionSetRep; - private: // representation =========================================================== diff --git a/src/static_vars.cc b/src/static_vars.cc index 6b7fc8a..dcb5b59 100644 --- a/src/static_vars.cc +++ b/src/static_vars.cc @@ -53,6 +53,7 @@ PageHeapAllocator Static::span_allocator_; PageHeapAllocator Static::stacktrace_allocator_; Span Static::sampled_objects_; std::atomic Static::growth_stacks_; +StaticStorage Static::pageheap_; void Static::InitStaticVars() { sizemap_.Init(); @@ -65,7 +66,7 @@ void Static::InitStaticVars() { central_cache_[i].Init(i); } - new (&pageheap_.memory) PageHeap(sizemap_.min_span_size_in_pages()); + new (pageheap()) PageHeap(sizemap_.min_span_size_in_pages()); #if defined(ENABLE_AGGRESSIVE_DECOMMIT_BY_DEFAULT) const bool kDefaultAggressiveDecommit = true; diff --git a/src/static_vars.h b/src/static_vars.h index 76199ad..d75b145 100644 --- a/src/static_vars.h +++ b/src/static_vars.h @@ -43,6 +43,7 @@ #include "base/basictypes.h" #include "base/spinlock.h" +#include "base/static_storage.h" #include "central_freelist.h" #include "common.h" #include "page_heap.h" @@ -74,7 +75,7 @@ class Static { // must be protected by pageheap_lock. // Page-level allocator. - static PageHeap* pageheap() { return reinterpret_cast(&pageheap_.memory); } + static PageHeap* pageheap() { return pageheap_.get(); } static PageHeapAllocator* span_allocator() { return &span_allocator_; } @@ -100,10 +101,7 @@ class Static { static bool IsInited() { return inited_; } private: - // some unit tests depend on this and link to static vars - // imperfectly. Thus we keep those unhidden for now. Thankfully - // they're not performance-critical. - /* ATTRIBUTE_HIDDEN */ static bool inited_; + ATTRIBUTE_HIDDEN static bool inited_; // These static variables require explicit initialization. We cannot // count on their constructors to do any initialization because other @@ -122,9 +120,7 @@ class Static { // is stored in trace->stack[kMaxStackDepth-1]. ATTRIBUTE_HIDDEN static std::atomic growth_stacks_; - /* ATTRIBUTE_HIDDEN */ static inline struct { - alignas(alignof(PageHeap)) std::byte memory[sizeof(PageHeap)]; - } pageheap_; + ATTRIBUTE_HIDDEN static StaticStorage pageheap_; }; } // namespace tcmalloc diff --git a/src/system-alloc.cc b/src/system-alloc.cc index c496d99..e47691e 100644 --- a/src/system-alloc.cc +++ b/src/system-alloc.cc @@ -47,6 +47,7 @@ #include "base/basictypes.h" #include "base/commandlineflags.h" #include "base/spinlock.h" // for SpinLockHolder, SpinLock, etc +#include "base/static_storage.h" #include "common.h" #include "internal_logging.h" @@ -126,10 +127,7 @@ public: } void* Alloc(size_t size, size_t *actual_size, size_t alignment); }; -static union { - char buf[sizeof(SbrkSysAllocator)]; - void *ptr; -} sbrk_space; +static tcmalloc::StaticStorage sbrk_space; class MmapSysAllocator : public SysAllocator { public: @@ -139,10 +137,7 @@ public: private: uintptr_t hint_ = 0; }; -static union { - char buf[sizeof(MmapSysAllocator)]; - void *ptr; -} mmap_space; +static tcmalloc::StaticStorage mmap_space; class DefaultSysAllocator : public SysAllocator { public: @@ -169,10 +164,7 @@ class DefaultSysAllocator : public SysAllocator { SysAllocator* allocs_[kMaxAllocators]; const char* names_[kMaxAllocators]; }; -static union { - char buf[sizeof(DefaultSysAllocator)]; - void *ptr; -} default_space; +static tcmalloc::StaticStorage default_space; static const char sbrk_name[] = "SbrkSysAllocator"; static const char mmap_name[] = "MmapSysAllocator"; @@ -367,8 +359,8 @@ SysAllocator *tc_get_sysalloc_override(SysAllocator *def) static bool system_alloc_inited = false; void InitSystemAllocators(void) { - MmapSysAllocator *mmap = new (mmap_space.buf) MmapSysAllocator(); - SbrkSysAllocator *sbrk = new (sbrk_space.buf) SbrkSysAllocator(); + MmapSysAllocator *mmap = mmap_space.Construct(); + SbrkSysAllocator *sbrk = sbrk_space.Construct(); // In 64-bit debug mode, place the mmap allocator first since it // allocates pointers that do not fit in 32 bits and therefore gives @@ -377,7 +369,7 @@ void InitSystemAllocators(void) { // likely to look like pointers and therefore the conservative gc in // the heap-checker is less likely to misinterpret a number as a // pointer). - DefaultSysAllocator *sdef = new (default_space.buf) DefaultSysAllocator(); + DefaultSysAllocator *sdef = default_space.Construct(); bool want_mmap = kDebugMode && (sizeof(void*) > 4); #if __sun__ // TODO: solaris has nice but annoying feature that makes it use diff --git a/src/tcmalloc.cc b/src/tcmalloc.cc index b902cfd..f71b09b 100644 --- a/src/tcmalloc.cc +++ b/src/tcmalloc.cc @@ -622,10 +622,8 @@ public: static TestingPortalImpl* Get() { static TestingPortalImpl* ptr = ([] () { - static struct { - alignas(TestingPortalImpl) char memory[sizeof(TestingPortalImpl)]; - } storage; - return new (storage.memory) TestingPortalImpl; + static StaticStorage storage; + return storage.Construct(); }()); return ptr; } @@ -1212,11 +1210,10 @@ static TCMallocGuard module_enter_exit_hook; #ifndef TCMALLOC_USING_DEBUGALLOCATION +static tcmalloc::StaticStorage malloc_impl_storage; + void SetupMallocExtension() { - static struct { - alignas(TCMallocImplementation) char memory[sizeof(TCMallocImplementation)]; - } storage; - MallocExtension::Register(new (storage.memory) TCMallocImplementation); + MallocExtension::Register(malloc_impl_storage.Construct()); } #endif // TCMALLOC_USING_DEBUGALLOCATION diff --git a/src/tests/tcmalloc_unittest.cc b/src/tests/tcmalloc_unittest.cc index 60afb93..58bfbbd 100644 --- a/src/tests/tcmalloc_unittest.cc +++ b/src/tests/tcmalloc_unittest.cc @@ -86,6 +86,7 @@ #include "base/function_ref.h" #include "base/cleanup.h" +#include "base/static_storage.h" #include "tests/testutil.h" @@ -205,13 +206,9 @@ struct OOMAbleSysAlloc : public SysAllocator { } }; -static union { - char buf[sizeof(OOMAbleSysAlloc)]; - void *ptr; -} test_sys_alloc_space; - static OOMAbleSysAlloc* get_test_sys_alloc() { - return reinterpret_cast(&test_sys_alloc_space); + static tcmalloc::StaticStorage storage; + return storage.get(); } void setup_oomable_sys_alloc() { diff --git a/src/thread_cache_ptr.cc b/src/thread_cache_ptr.cc index f84d366..cfae8df 100644 --- a/src/thread_cache_ptr.cc +++ b/src/thread_cache_ptr.cc @@ -50,9 +50,8 @@ SpinLock init_cache_lock; bool init_cache_ready; ThreadCache* GetInitCache() { - alignas(ThreadCache) static std::byte init_cache_storage[sizeof(ThreadCache)]; - - return reinterpret_cast(init_cache_storage); + static StaticStorage storage; + return storage.get(); } } // namespace