Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 1 | //===- Memory.h -------------------------------------------------*- C++ -*-===// |
| 2 | // |
Andrew Walbran | 16937d0 | 2019-10-22 13:54:20 +0100 | [diff] [blame] | 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| 4 | // See https://llvm.org/LICENSE.txt for license information. |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 6 | // |
| 7 | //===----------------------------------------------------------------------===// |
| 8 | // |
| 9 | // This file defines arena allocators. |
| 10 | // |
| 11 | // Almost all large objects, such as files, sections or symbols, are |
| 12 | // used for the entire lifetime of the linker once they are created. |
| 13 | // This usage characteristic makes arena allocator an attractive choice |
| 14 | // where the entire linker is one arena. With an arena, newly created |
| 15 | // objects belong to the arena and freed all at once when everything is done. |
| 16 | // Arena allocators are efficient and easy to understand. |
| 17 | // Most objects are allocated using the arena allocators defined by this file. |
| 18 | // |
| 19 | //===----------------------------------------------------------------------===// |
| 20 | |
| 21 | #ifndef LLD_COMMON_MEMORY_H |
| 22 | #define LLD_COMMON_MEMORY_H |
| 23 | |
| 24 | #include "llvm/Support/Allocator.h" |
| 25 | #include "llvm/Support/StringSaver.h" |
| 26 | #include <vector> |
| 27 | |
| 28 | namespace lld { |
| 29 | |
| 30 | // Use this arena if your object doesn't have a destructor. |
Andrew Walbran | 3d2c197 | 2020-04-07 12:24:26 +0100 | [diff] [blame] | 31 | extern llvm::BumpPtrAllocator bAlloc; |
| 32 | extern llvm::StringSaver saver; |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 33 | |
| 34 | void freeArena(); |
| 35 | |
| 36 | // These two classes are hack to keep track of all |
| 37 | // SpecificBumpPtrAllocator instances. |
| 38 | struct SpecificAllocBase { |
Andrew Walbran | 3d2c197 | 2020-04-07 12:24:26 +0100 | [diff] [blame] | 39 | SpecificAllocBase() { instances.push_back(this); } |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 40 | virtual ~SpecificAllocBase() = default; |
| 41 | virtual void reset() = 0; |
Andrew Walbran | 3d2c197 | 2020-04-07 12:24:26 +0100 | [diff] [blame] | 42 | static std::vector<SpecificAllocBase *> instances; |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 43 | }; |
| 44 | |
| 45 | template <class T> struct SpecificAlloc : public SpecificAllocBase { |
Andrew Walbran | 3d2c197 | 2020-04-07 12:24:26 +0100 | [diff] [blame] | 46 | void reset() override { alloc.DestroyAll(); } |
| 47 | llvm::SpecificBumpPtrAllocator<T> alloc; |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 48 | }; |
| 49 | |
Olivier Deprez | f4ef2d0 | 2021-04-20 13:36:24 +0200 | [diff] [blame] | 50 | // Use a static local for these singletons so they are only registered if an |
| 51 | // object of this instance is ever constructed. Otherwise we will create and |
| 52 | // register ELF allocators for COFF and the reverse. |
| 53 | template <typename T> |
| 54 | inline llvm::SpecificBumpPtrAllocator<T> &getSpecificAllocSingleton() { |
| 55 | static SpecificAlloc<T> instance; |
| 56 | return instance.alloc; |
| 57 | } |
| 58 | |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 59 | // Use this arena if your object has a destructor. |
| 60 | // Your destructor will be invoked from freeArena(). |
Andrew Walbran | 3d2c197 | 2020-04-07 12:24:26 +0100 | [diff] [blame] | 61 | template <typename T, typename... U> T *make(U &&... args) { |
Olivier Deprez | f4ef2d0 | 2021-04-20 13:36:24 +0200 | [diff] [blame] | 62 | return new (getSpecificAllocSingleton<T>().Allocate()) |
| 63 | T(std::forward<U>(args)...); |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 64 | } |
| 65 | |
| 66 | } // namespace lld |
| 67 | |
| 68 | #endif |