1//===- Memory.h -------------------------------------------------*- C++ -*-===// 2// 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 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 26namespace lld { 27// A base class only used by the CommonLinkerContext to keep track of the 28// SpecificAlloc<> instances. 29struct SpecificAllocBase { 30 virtual ~SpecificAllocBase() = default; 31 static SpecificAllocBase *getOrCreate(void *tag, size_t size, size_t align, 32 SpecificAllocBase *(&creator)(void *)); 33}; 34 35// An arena of specific types T, created on-demand. 36template <class T> struct SpecificAlloc : public SpecificAllocBase { 37 static SpecificAllocBase *create(void *storage) { 38 return new (storage) SpecificAlloc<T>(); 39 } 40 llvm::SpecificBumpPtrAllocator<T> alloc; 41 static int tag; 42}; 43 44// The address of this static member is only used as a key in 45// CommonLinkerContext::instances. Its value does not matter. 46template <class T> int SpecificAlloc<T>::tag = 0; 47 48// Creates the arena on-demand on the first call; or returns it, if it was 49// already created. 50template <typename T> 51inline llvm::SpecificBumpPtrAllocator<T> &getSpecificAllocSingleton() { 52 SpecificAllocBase *instance = SpecificAllocBase::getOrCreate( 53 &SpecificAlloc<T>::tag, sizeof(SpecificAlloc<T>), 54 alignof(SpecificAlloc<T>), SpecificAlloc<T>::create); 55 return ((SpecificAlloc<T> *)instance)->alloc; 56} 57 58// Creates new instances of T off a (almost) contiguous arena/object pool. The 59// instances are destroyed whenever lldMain() goes out of scope. 60template <typename T, typename... U> T *make(U &&... args) { 61 return new (getSpecificAllocSingleton<T>().Allocate()) 62 T(std::forward<U>(args)...); 63} 64 65template <typename T> 66inline llvm::SpecificBumpPtrAllocator<T> & 67getSpecificAllocSingletonThreadLocal() { 68 thread_local SpecificAlloc<T> instance; 69 return instance.alloc; 70} 71 72// Create a new instance of T off a thread-local SpecificAlloc, used by code 73// like parallel input section initialization. The use cases assume that the 74// return value outlives the containing parallelForEach (if exists), which is 75// currently guaranteed: when parallelForEach returns, the threads allocating 76// the TLS are not destroyed. 77// 78// Note: Some ports (e.g. ELF) have lots of global states which are currently 79// infeasible to remove, and context() just adds overhead with no benefit. The 80// allocation performance is of higher importance, so we simply use thread_local 81// allocators instead of doing context indirection and pthread_getspecific. 82template <typename T, typename... U> T *makeThreadLocal(U &&...args) { 83 return new (getSpecificAllocSingletonThreadLocal<T>().Allocate()) 84 T(std::forward<U>(args)...); 85} 86 87template <typename T> T *makeThreadLocalN(size_t n) { 88 return new (getSpecificAllocSingletonThreadLocal<T>().Allocate(n)) T[n]; 89} 90 91} // namespace lld 92 93#endif 94