[Alignment][NFC] Use Align with TargetLowering::setMinFunctionAlignment
[llvm-core.git] / include / llvm / ExecutionEngine / Orc / SymbolStringPool.h
blobc354f6c3559cc0ae9861e25bd0b0d56cae4e5b65
1 //===- SymbolStringPool.h - Multi-threaded pool for JIT symbols -*- 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 // Contains a multi-threaded string pool suitable for use with ORC.
11 //===----------------------------------------------------------------------===//
13 #ifndef LLVM_EXECUTIONENGINE_ORC_SYMBOLSTRINGPOOL_H
14 #define LLVM_EXECUTIONENGINE_ORC_SYMBOLSTRINGPOOL_H
16 #include "llvm/ADT/DenseMap.h"
17 #include "llvm/ADT/StringMap.h"
18 #include <atomic>
19 #include <mutex>
21 namespace llvm {
22 namespace orc {
24 class SymbolStringPtr;
26 /// String pool for symbol names used by the JIT.
27 class SymbolStringPool {
28 friend class SymbolStringPtr;
29 public:
30 /// Destroy a SymbolStringPool.
31 ~SymbolStringPool();
33 /// Create a symbol string pointer from the given string.
34 SymbolStringPtr intern(StringRef S);
36 /// Remove from the pool any entries that are no longer referenced.
37 void clearDeadEntries();
39 /// Returns true if the pool is empty.
40 bool empty() const;
41 private:
42 using RefCountType = std::atomic<size_t>;
43 using PoolMap = StringMap<RefCountType>;
44 using PoolMapEntry = StringMapEntry<RefCountType>;
45 mutable std::mutex PoolMutex;
46 PoolMap Pool;
49 /// Pointer to a pooled string representing a symbol name.
50 class SymbolStringPtr {
51 friend class SymbolStringPool;
52 friend struct DenseMapInfo<SymbolStringPtr>;
54 public:
55 SymbolStringPtr() = default;
56 SymbolStringPtr(const SymbolStringPtr &Other)
57 : S(Other.S) {
58 if (isRealPoolEntry(S))
59 ++S->getValue();
62 SymbolStringPtr& operator=(const SymbolStringPtr &Other) {
63 if (isRealPoolEntry(S))
64 --S->getValue();
65 S = Other.S;
66 if (isRealPoolEntry(S))
67 ++S->getValue();
68 return *this;
71 SymbolStringPtr(SymbolStringPtr &&Other) : S(nullptr) {
72 std::swap(S, Other.S);
75 SymbolStringPtr& operator=(SymbolStringPtr &&Other) {
76 if (isRealPoolEntry(S))
77 --S->getValue();
78 S = nullptr;
79 std::swap(S, Other.S);
80 return *this;
83 ~SymbolStringPtr() {
84 if (isRealPoolEntry(S))
85 --S->getValue();
88 StringRef operator*() const { return S->first(); }
90 friend bool operator==(const SymbolStringPtr &LHS,
91 const SymbolStringPtr &RHS) {
92 return LHS.S == RHS.S;
95 friend bool operator!=(const SymbolStringPtr &LHS,
96 const SymbolStringPtr &RHS) {
97 return !(LHS == RHS);
100 friend bool operator<(const SymbolStringPtr &LHS,
101 const SymbolStringPtr &RHS) {
102 return LHS.S < RHS.S;
105 private:
106 using PoolEntryPtr = SymbolStringPool::PoolMapEntry *;
108 SymbolStringPtr(SymbolStringPool::PoolMapEntry *S)
109 : S(S) {
110 if (isRealPoolEntry(S))
111 ++S->getValue();
114 // Returns false for null, empty, and tombstone values, true otherwise.
115 bool isRealPoolEntry(PoolEntryPtr P) {
116 return ((reinterpret_cast<uintptr_t>(P) - 1) & InvalidPtrMask) !=
117 InvalidPtrMask;
120 static SymbolStringPtr getEmptyVal() {
121 return SymbolStringPtr(reinterpret_cast<PoolEntryPtr>(EmptyBitPattern));
124 static SymbolStringPtr getTombstoneVal() {
125 return SymbolStringPtr(reinterpret_cast<PoolEntryPtr>(TombstoneBitPattern));
128 constexpr static uintptr_t EmptyBitPattern =
129 std::numeric_limits<uintptr_t>::max()
130 << PointerLikeTypeTraits<PoolEntryPtr>::NumLowBitsAvailable;
132 constexpr static uintptr_t TombstoneBitPattern =
133 (std::numeric_limits<uintptr_t>::max() - 1)
134 << PointerLikeTypeTraits<PoolEntryPtr>::NumLowBitsAvailable;
136 constexpr static uintptr_t InvalidPtrMask =
137 (std::numeric_limits<uintptr_t>::max() - 3)
138 << PointerLikeTypeTraits<PoolEntryPtr>::NumLowBitsAvailable;
140 PoolEntryPtr S = nullptr;
143 inline SymbolStringPool::~SymbolStringPool() {
144 #ifndef NDEBUG
145 clearDeadEntries();
146 assert(Pool.empty() && "Dangling references at pool destruction time");
147 #endif // NDEBUG
150 inline SymbolStringPtr SymbolStringPool::intern(StringRef S) {
151 std::lock_guard<std::mutex> Lock(PoolMutex);
152 PoolMap::iterator I;
153 bool Added;
154 std::tie(I, Added) = Pool.try_emplace(S, 0);
155 return SymbolStringPtr(&*I);
158 inline void SymbolStringPool::clearDeadEntries() {
159 std::lock_guard<std::mutex> Lock(PoolMutex);
160 for (auto I = Pool.begin(), E = Pool.end(); I != E;) {
161 auto Tmp = I++;
162 if (Tmp->second == 0)
163 Pool.erase(Tmp);
167 inline bool SymbolStringPool::empty() const {
168 std::lock_guard<std::mutex> Lock(PoolMutex);
169 return Pool.empty();
172 } // end namespace orc
174 template <>
175 struct DenseMapInfo<orc::SymbolStringPtr> {
177 static orc::SymbolStringPtr getEmptyKey() {
178 return orc::SymbolStringPtr::getEmptyVal();
181 static orc::SymbolStringPtr getTombstoneKey() {
182 return orc::SymbolStringPtr::getTombstoneVal();
185 static unsigned getHashValue(const orc::SymbolStringPtr &V) {
186 return DenseMapInfo<orc::SymbolStringPtr::PoolEntryPtr>::getHashValue(V.S);
189 static bool isEqual(const orc::SymbolStringPtr &LHS,
190 const orc::SymbolStringPtr &RHS) {
191 return LHS.S == RHS.S;
195 } // end namespace llvm
197 #endif // LLVM_EXECUTIONENGINE_ORC_SYMBOLSTRINGPOOL_H