[lld] f6bd0a8 - [ELF] Add makeThreadLocal/makeThreadLocalN and remove InputFile::localSymStorage

Fangrui Song via llvm-commits llvm-commits at lists.llvm.org
Thu Aug 4 11:09:45 PDT 2022


Author: Fangrui Song
Date: 2022-08-04T11:09:40-07:00
New Revision: f6bd0a8f2bc4b62f7f7800a7dd1de6ba764b56c6

URL: https://github.com/llvm/llvm-project/commit/f6bd0a8f2bc4b62f7f7800a7dd1de6ba764b56c6
DIFF: https://github.com/llvm/llvm-project/commit/f6bd0a8f2bc4b62f7f7800a7dd1de6ba764b56c6.diff

LOG: [ELF] Add makeThreadLocal/makeThreadLocalN and remove InputFile::localSymStorage

makeThreadLocal/makeThreadLocalN are moved from D130810 ([ELF] Parallelize input
section initialization) here to make D130810 more focused on the refactor:

* COFF has some needs for multiple linker contexts. D108850 partially removed
  global states from lldCommon but left the global variable `lctx`.
* To the best of my knowledge, all multiple-linker-context feature requests to
  ELF are more from user convenience, with no very strong argument.
* In practice, ELF port is very difficult to remove global states without
  introducing significant performance regression/hurting code readability.
* Per-thread allocators from D122922/D123879 are too expensive and will not
  really benefit ELF.

This patch adds a simple thread_local based makeThreadLocal to
lld/Common/Memory.h. It will enable further optimization in ELF.

Added: 
    

Modified: 
    lld/ELF/InputFiles.cpp
    lld/ELF/InputFiles.h
    lld/include/lld/Common/Memory.h

Removed: 
    


################################################################################
diff  --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp
index 378023abc1928..560e24f5e9233 100644
--- a/lld/ELF/InputFiles.cpp
+++ b/lld/ELF/InputFiles.cpp
@@ -1066,8 +1066,7 @@ void ObjFile<ELFT>::initializeSymbols(const object::ELFFile<ELFT> &obj) {
 template <class ELFT> void ObjFile<ELFT>::initializeLocalSymbols() {
   if (!firstGlobal)
     return;
-  localSymStorage = std::make_unique<SymbolUnion[]>(firstGlobal);
-  SymbolUnion *locals = localSymStorage.get();
+  SymbolUnion *locals = makeThreadLocalN<SymbolUnion>(firstGlobal);
 
   ArrayRef<Elf_Sym> eSyms = this->getELFSyms<ELFT>();
   for (size_t i = 0, end = firstGlobal; i != end; ++i) {

diff  --git a/lld/ELF/InputFiles.h b/lld/ELF/InputFiles.h
index a24e664a7e168..dd9f7328a103c 100644
--- a/lld/ELF/InputFiles.h
+++ b/lld/ELF/InputFiles.h
@@ -304,9 +304,6 @@ template <class ELFT> class ObjFile : public ELFFileBase {
   // If the section does not exist (which is common), the array is empty.
   ArrayRef<Elf_Word> shndxTable;
 
-  // Storage for local symbols.
-  std::unique_ptr<SymbolUnion[]> localSymStorage;
-
   // Debugging information to retrieve source file and line for error
   // reporting. Linker may find reasonable number of errors in a
   // single object file, so we cache debugging information in order to

diff  --git a/lld/include/lld/Common/Memory.h b/lld/include/lld/Common/Memory.h
index 0b2f474c30135..c7612a08c6b00 100644
--- a/lld/include/lld/Common/Memory.h
+++ b/lld/include/lld/Common/Memory.h
@@ -62,6 +62,32 @@ template <typename T, typename... U> T *make(U &&... args) {
       T(std::forward<U>(args)...);
 }
 
+template <typename T>
+inline llvm::SpecificBumpPtrAllocator<T> &
+getSpecificAllocSingletonThreadLocal() {
+  thread_local SpecificAlloc<T> instance;
+  return instance.alloc;
+}
+
+// Create a new instance of T off a thread-local SpecificAlloc, used by code
+// like parallel input section initialization. The use cases assume that the
+// return value outlives the containing parallelForEach (if exists), which is
+// currently guaranteed: when parallelForEach returns, the threads allocating
+// the TLS are not destroyed.
+//
+// Note: Some ports (e.g. ELF) have lots of global states which are currently
+// infeasible to remove, and context() just adds overhead with no benefit. The
+// allocation performance is of higher importance, so we simply use thread_local
+// allocators instead of doing context indirection and pthread_getspecific.
+template <typename T, typename... U> T *makeThreadLocal(U &&...args) {
+  return new (getSpecificAllocSingletonThreadLocal<T>().Allocate())
+      T(std::forward<U>(args)...);
+}
+
+template <typename T> T *makeThreadLocalN(size_t n) {
+  return new (getSpecificAllocSingletonThreadLocal<T>().Allocate(n)) T[n];
+}
+
 } // namespace lld
 
 #endif


        


More information about the llvm-commits mailing list