[LLD] Have only one SpecificAllocator per type
authorReid Kleckner <rnk@google.com>
Tue, 2 Jun 2020 20:58:50 +0000 (13:58 -0700)
committerReid Kleckner <rnk@google.com>
Tue, 2 Jun 2020 21:09:09 +0000 (14:09 -0700)
Previously, the SpecificAllocator was a static local in the `make<T>`
function template. Using static locals is nice because they are only
constructed and registered if they are accessed. However, if there are
multiple calls to make<> with different constructor parameters, we would
get multiple static local variable instances. This is undesirable and
leads to extra memory allocations. I noticed there were two sources of
DefinedRegular allocations while checking heap profiles.

lld/include/lld/Common/Memory.h

index 41d8f15..f516a32 100644 (file)
@@ -47,11 +47,20 @@ template <class T> struct SpecificAlloc : public SpecificAllocBase {
   llvm::SpecificBumpPtrAllocator<T> alloc;
 };
 
+// Use a static local for these singletons so they are only registered if an
+// object of this instance is ever constructed. Otherwise we will create and
+// register ELF allocators for COFF and the reverse.
+template <typename T>
+inline llvm::SpecificBumpPtrAllocator<T> &getSpecificAllocSingleton() {
+  static SpecificAlloc<T> instance;
+  return instance.alloc;
+}
+
 // Use this arena if your object has a destructor.
 // Your destructor will be invoked from freeArena().
 template <typename T, typename... U> T *make(U &&... args) {
-  static SpecificAlloc<T> alloc;
-  return new (alloc.alloc.Allocate()) T(std::forward<U>(args)...);
+  return new (getSpecificAllocSingleton<T>().Allocate())
+      T(std::forward<U>(args)...);
 }
 
 } // namespace lld