Index: ELF/Driver.cpp =================================================================== --- ELF/Driver.cpp +++ ELF/Driver.cpp @@ -54,7 +54,6 @@ ScriptConfig = ≻ Driver->main(Args, CanExitEarly); - InputFile::freePool(); freeArena(); return !HasError; } @@ -132,7 +131,7 @@ MemoryBufferRef MBRef = *Buffer; if (InBinary) { - Files.push_back(new BinaryFile(MBRef)); + Files.push_back(new (alloc()) BinaryFile(MBRef)); return; } @@ -146,7 +145,7 @@ Files.push_back(createObjectFile(MB, Path)); return; } - Files.push_back(new ArchiveFile(MBRef)); + Files.push_back(new (alloc()) ArchiveFile(MBRef)); return; case file_magic::elf_shared_object: if (Config->Relocatable) { @@ -157,7 +156,7 @@ return; default: if (InLib) - Files.push_back(new LazyObjectFile(MBRef)); + Files.push_back(new (alloc()) LazyObjectFile(MBRef)); else Files.push_back(createObjectFile(MBRef)); } Index: ELF/InputFiles.h =================================================================== --- ELF/InputFiles.h +++ ELF/InputFiles.h @@ -37,21 +37,6 @@ namespace lld { namespace elf { -template struct GAlloc { - static llvm::SpecificBumpPtrAllocator> IAlloc; - static llvm::SpecificBumpPtrAllocator> MAlloc; - static llvm::SpecificBumpPtrAllocator> EHAlloc; -}; - -template -llvm::SpecificBumpPtrAllocator> GAlloc::IAlloc; - -template -llvm::SpecificBumpPtrAllocator> GAlloc::MAlloc; - -template -llvm::SpecificBumpPtrAllocator> GAlloc::EHAlloc; - using llvm::object::Archive; class InputFile; @@ -76,8 +61,6 @@ // The root class of input files. class InputFile { public: - virtual ~InputFile() = default; - enum Kind { ObjectKind, SharedKind, @@ -109,19 +92,11 @@ uint16_t EMachine = llvm::ELF::EM_NONE; uint8_t OSABI = 0; - static void freePool(); - protected: - InputFile(Kind K, MemoryBufferRef M) : MB(M), FileKind(K) { - Pool.push_back(this); - } + InputFile(Kind K, MemoryBufferRef M) : MB(M), FileKind(K) {} private: const Kind FileKind; - - // All InputFile instances are added to the pool - // and freed all at once on exit by freePool(). - static std::vector Pool; }; // Returns "(internal)", "foo.a(bar.o)" or "baz.o". Index: ELF/InputFiles.cpp =================================================================== --- ELF/InputFiles.cpp +++ ELF/InputFiles.cpp @@ -34,8 +34,6 @@ using namespace lld; using namespace lld::elf; -std::vector InputFile::Pool; - template DIHelper::DIHelper(elf::InputFile *F) { Expected> Obj = object::ObjectFile::createObjectFile(F->MB); @@ -69,15 +67,6 @@ : ""; } -// Deletes all InputFile instances created so far. -void InputFile::freePool() { - // Files are freed in reverse order so that files created - // from other files (e.g. object files extracted from archives) - // are freed in the proper order. - for (int I = Pool.size() - 1; I >= 0; --I) - delete Pool[I]; -} - // Returns "(internal)", "foo.a(bar.o)" or "baz.o". std::string elf::getFilename(const InputFile *F) { if (!F) @@ -387,7 +376,7 @@ // If -r is given, we do not interpret or apply relocation // but just copy relocation sections to output. if (Config->Relocatable) - return new (GAlloc::IAlloc.Allocate()) + return new (alloc>()) InputSection(this, &Sec, Name); // Find the relocation target section and associate this @@ -430,14 +419,13 @@ // .eh_frame_hdr section for runtime. So we handle them with a special // class. For relocatable outputs, they are just passed through. if (Name == ".eh_frame" && !Config->Relocatable) - return new (GAlloc::EHAlloc.Allocate()) + return new (alloc>()) EhInputSection(this, &Sec, Name); if (shouldMerge(Sec)) - return new (GAlloc::MAlloc.Allocate()) + return new (alloc>()) MergeInputSection(this, &Sec, Name); - return new (GAlloc::IAlloc.Allocate()) - InputSection(this, &Sec, Name); + return new (alloc>()) InputSection(this, &Sec, Name); } template void elf::ObjectFile::initializeSymbols() { @@ -806,13 +794,13 @@ InputFile *Obj; if (Size == ELFCLASS32 && Endian == ELFDATA2LSB) - Obj = new T(MB); + Obj = new (alloc>()) T(MB); else if (Size == ELFCLASS32 && Endian == ELFDATA2MSB) - Obj = new T(MB); + Obj = new (alloc>()) T(MB); else if (Size == ELFCLASS64 && Endian == ELFDATA2LSB) - Obj = new T(MB); + Obj = new (alloc>()) T(MB); else if (Size == ELFCLASS64 && Endian == ELFDATA2MSB) - Obj = new T(MB); + Obj = new (alloc>()) T(MB); else fatal("invalid file class: " + MB.getBufferIdentifier()); Index: ELF/Memory.h =================================================================== --- ELF/Memory.h +++ ELF/Memory.h @@ -24,12 +24,36 @@ #include "llvm/Support/Allocator.h" #include "llvm/Support/StringSaver.h" +#include namespace lld { namespace elf { + +// Use this arena if your object doesn't have a destructor. extern llvm::BumpPtrAllocator BAlloc; extern llvm::StringSaver Saver; +// These two classes are hack to keep track of all +// SpecificBumpPtrAllocator instances. +struct SpecificAllocBase { + SpecificAllocBase(); + virtual ~SpecificAllocBase() = default; + virtual void reset() = 0; + static std::vector Instances; +}; + +template struct SpecificAlloc : public SpecificAllocBase { + void reset() override { Alloc.DestroyAll(); } + llvm::SpecificBumpPtrAllocator Alloc; +}; + +// Use this arean if your object have a destructor. +// Your destructor will be invoked from freeArena(). +template static T *alloc() { + static SpecificAlloc Alloc; + return Alloc.Alloc.Allocate(); +} + void freeArena(); } } Index: ELF/Memory.cpp =================================================================== --- ELF/Memory.cpp +++ ELF/Memory.cpp @@ -9,7 +9,19 @@ #include "Memory.h" -llvm::BumpPtrAllocator lld::elf::BAlloc; -llvm::StringSaver lld::elf::Saver{BAlloc}; +using namespace llvm; +using namespace lld; +using namespace lld::elf; -void lld::elf::freeArena() { BAlloc.Reset(); } +BumpPtrAllocator elf::BAlloc; +StringSaver elf::Saver{BAlloc}; + +SpecificAllocBase::SpecificAllocBase() { Instances.push_back(this); } + +std::vector SpecificAllocBase::Instances; + +void elf::freeArena() { + for (SpecificAllocBase *Alloc : SpecificAllocBase::Instances) + Alloc->reset(); + BAlloc.Reset(); +}