LLVM 22.0.0git
SymbolStringPool.h
Go to the documentation of this file.
1//===-- SymbolStringPool.h -- Thread-safe 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 thread-safe string pool suitable for use with ORC.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef LLVM_EXECUTIONENGINE_ORC_SYMBOLSTRINGPOOL_H
14#define LLVM_EXECUTIONENGINE_ORC_SYMBOLSTRINGPOOL_H
15
16#include "llvm/ADT/DenseMap.h"
17#include "llvm/ADT/Hashing.h"
18#include "llvm/ADT/StringMap.h"
20#include <atomic>
21#include <mutex>
22
23namespace llvm {
24
25class raw_ostream;
26
27namespace orc {
28
30class SymbolStringPtr;
32
33/// String pool for symbol names used by the JIT.
36 friend class SymbolStringPtrBase;
38
39 // Implemented in DebugUtils.h.
41 const SymbolStringPool &SSP);
42
43public:
44 /// Destroy a SymbolStringPool.
46
47 /// Create a symbol string pointer from the given string.
49
50 /// Remove from the pool any entries that are no longer referenced.
51 void clearDeadEntries();
52
53 /// Returns true if the pool is empty.
54 bool empty() const;
55
56private:
57 size_t getRefCount(const SymbolStringPtrBase &S) const;
58
59 using RefCountType = std::atomic<size_t>;
60 using PoolMap = StringMap<RefCountType>;
61 using PoolMapEntry = StringMapEntry<RefCountType>;
62 mutable std::mutex PoolMutex;
63 PoolMap Pool;
64};
65
66/// Base class for both owning and non-owning symbol-string ptrs.
67///
68/// All symbol-string ptrs are convertible to bool, dereferenceable and
69/// comparable.
70///
71/// SymbolStringPtrBases are default-constructible and constructible
72/// from nullptr to enable comparison with these values.
74 friend class SymbolStringPool;
76 friend struct DenseMapInfo<SymbolStringPtr>;
78
79public:
81 SymbolStringPtrBase(std::nullptr_t) {}
82
83 explicit operator bool() const { return S; }
84
85 StringRef operator*() const { return S->first(); }
86
88 return LHS.S == RHS.S;
89 }
90
92 return !(LHS == RHS);
93 }
94
96 return LHS.S < RHS.S;
97 }
98
100 const SymbolStringPtrBase &Sym);
101
102#ifndef NDEBUG
103 // Returns true if the pool entry's ref count is above zero (or if the entry
104 // is an empty or tombstone value). Useful for debugging and testing -- this
105 // method can be used to identify SymbolStringPtrs and
106 // NonOwningSymbolStringPtrs that are pointing to abandoned pool entries.
107 bool poolEntryIsAlive() const {
108 return isRealPoolEntry(S) ? S->getValue() != 0 : true;
109 }
110#endif
111
112protected:
113 using PoolEntry = SymbolStringPool::PoolMapEntry;
115
117
118 constexpr static uintptr_t EmptyBitPattern =
119 std::numeric_limits<uintptr_t>::max()
121
122 constexpr static uintptr_t TombstoneBitPattern =
123 (std::numeric_limits<uintptr_t>::max() - 1)
125
126 constexpr static uintptr_t InvalidPtrMask =
127 (std::numeric_limits<uintptr_t>::max() - 3)
129
130 // Returns false for null, empty, and tombstone values, true otherwise.
132 return ((reinterpret_cast<uintptr_t>(P) - 1) & InvalidPtrMask) !=
134 }
135
136 size_t getRefCount() const {
137 return isRealPoolEntry(S) ? size_t(S->getValue()) : size_t(0);
138 }
139
140 PoolEntryPtr S = nullptr;
141};
142
143/// Pointer to a pooled string representing a symbol name.
145 friend class SymbolStringPool;
147 friend struct DenseMapInfo<SymbolStringPtr>;
148
149public:
150 SymbolStringPtr() = default;
151 SymbolStringPtr(std::nullptr_t) {}
155
157
159 decRef();
160 S = Other.S;
161 incRef();
162 return *this;
163 }
164
166
168 decRef();
169 S = nullptr;
170 std::swap(S, Other.S);
171 return *this;
172 }
173
174 ~SymbolStringPtr() { decRef(); }
175
176private:
178
179 void incRef() {
180 if (isRealPoolEntry(S))
181 ++S->getValue();
182 }
183
184 void decRef() {
185 if (isRealPoolEntry(S)) {
186 assert(S->getValue() && "Releasing SymbolStringPtr with zero ref count");
187 --S->getValue();
188 }
189 }
190
191 static SymbolStringPtr getEmptyVal() {
192 return SymbolStringPtr(reinterpret_cast<PoolEntryPtr>(EmptyBitPattern));
193 }
194
195 static SymbolStringPtr getTombstoneVal() {
196 return SymbolStringPtr(reinterpret_cast<PoolEntryPtr>(TombstoneBitPattern));
197 }
198};
199
200/// Provides unsafe access to ownership operations on SymbolStringPtr.
201/// This class can be used to manage SymbolStringPtr instances from C.
203public:
204 using PoolEntry = SymbolStringPool::PoolMapEntry;
205
207
208 /// Create an unsafe pool entry ref without changing the ref-count.
210 return S.S;
211 }
212
213 /// Consumes the given SymbolStringPtr without releasing the pool entry.
215 PoolEntry *E = nullptr;
216 std::swap(E, S.S);
217 return E;
218 }
219
220 PoolEntry *rawPtr() { return E; }
221
222 /// Creates a SymbolStringPtr for this entry, with the SymbolStringPtr
223 /// retaining the entry as usual.
225
226 /// Creates a SymbolStringPtr for this entry *without* performing a retain
227 /// operation during construction.
230 std::swap(S.S, E);
231 return S;
232 }
233
234 void retain() { ++E->getValue(); }
235 void release() { --E->getValue(); }
236
237private:
238 PoolEntry *E = nullptr;
239};
240
241/// Non-owning SymbolStringPool entry pointer. Instances are comparable with
242/// SymbolStringPtr instances and guaranteed to have the same hash, but do not
243/// affect the ref-count of the pooled string (and are therefore cheaper to
244/// copy).
245///
246/// NonOwningSymbolStringPtrs are silently invalidated if the pool entry's
247/// ref-count drops to zero, so they should only be used in contexts where a
248/// corresponding SymbolStringPtr is known to exist (which will guarantee that
249/// the ref-count stays above zero). E.g. in a graph where nodes are
250/// represented by SymbolStringPtrs the edges can be represented by pairs of
251/// NonOwningSymbolStringPtrs and this will make the introduction of deletion
252/// of edges cheaper.
255
256public:
258 explicit NonOwningSymbolStringPtr(const SymbolStringPtr &S)
259 : SymbolStringPtrBase(S) {}
260
261 using SymbolStringPtrBase::operator=;
262
263private:
265
266 static NonOwningSymbolStringPtr getEmptyVal() {
268 reinterpret_cast<PoolEntryPtr>(EmptyBitPattern));
269 }
270
271 static NonOwningSymbolStringPtr getTombstoneVal() {
273 reinterpret_cast<PoolEntryPtr>(TombstoneBitPattern));
274 }
275};
276
280 "SymbolStringPtr constructed from invalid non-owning pointer.");
281
282 if (isRealPoolEntry(S))
283 ++S->getValue();
284}
285
287#ifndef NDEBUG
289 assert(Pool.empty() && "Dangling references at pool destruction time");
290#endif // NDEBUG
291}
292
294 std::lock_guard<std::mutex> Lock(PoolMutex);
296 bool Added;
297 std::tie(I, Added) = Pool.try_emplace(S, 0);
298 return SymbolStringPtr(&*I);
299}
300
302 std::lock_guard<std::mutex> Lock(PoolMutex);
303 for (auto I = Pool.begin(), E = Pool.end(); I != E;) {
304 auto Tmp = I++;
305 if (Tmp->second == 0)
306 Pool.erase(Tmp);
307 }
308}
309
310inline bool SymbolStringPool::empty() const {
311 std::lock_guard<std::mutex> Lock(PoolMutex);
312 return Pool.empty();
313}
314
315inline size_t
316SymbolStringPool::getRefCount(const SymbolStringPtrBase &S) const {
317 return S.getRefCount();
318}
319
321 const SymbolStringPtrBase &Sym);
322
326
327} // end namespace orc
328
329template <>
330struct DenseMapInfo<orc::SymbolStringPtr> {
331
333 return orc::SymbolStringPtr::getEmptyVal();
334 }
335
337 return orc::SymbolStringPtr::getTombstoneVal();
338 }
339
343
346 return LHS.S == RHS.S;
347 }
348};
349
350template <> struct DenseMapInfo<orc::NonOwningSymbolStringPtr> {
351
353 return orc::NonOwningSymbolStringPtr::getEmptyVal();
354 }
355
357 return orc::NonOwningSymbolStringPtr::getTombstoneVal();
358 }
359
364
367 return LHS.S == RHS.S;
368 }
369};
370
371} // end namespace llvm
372
373#endif // LLVM_EXECUTIONENGINE_ORC_SYMBOLSTRINGPOOL_H
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file defines the StringMap class.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define LLVM_ABI
Definition Compiler.h:213
This file defines the DenseMap class.
#define I(x, y, z)
Definition MD5.cpp:58
#define P(N)
Value * RHS
Value * LHS
const ValueTy & getValue() const
StringMapEntry - This is used to represent one value that is inserted into a StringMap.
StringMap - This is an unconventional map that is specialized for handling keys that are "strings",...
Definition StringMap.h:133
StringMapIterBase< RefCountType, false > iterator
Definition StringMap.h:221
StringRef - Represent a constant reference to a string, i.e.
Definition StringRef.h:55
An opaque object representing a hash code.
Definition Hashing.h:76
Non-owning SymbolStringPool entry pointer.
SymbolStringPool::PoolMapEntry PoolEntry
SymbolStringPtr copyToSymbolStringPtr()
Creates a SymbolStringPtr for this entry, with the SymbolStringPtr retaining the entry as usual.
static SymbolStringPoolEntryUnsafe from(const SymbolStringPtrBase &S)
Create an unsafe pool entry ref without changing the ref-count.
static SymbolStringPoolEntryUnsafe take(SymbolStringPtr &&S)
Consumes the given SymbolStringPtr without releasing the pool entry.
SymbolStringPtr moveToSymbolStringPtr()
Creates a SymbolStringPtr for this entry without performing a retain operation during construction.
String pool for symbol names used by the JIT.
LLVM_ABI friend raw_ostream & operator<<(raw_ostream &OS, const SymbolStringPool &SSP)
Dump a SymbolStringPool. Useful for debugging dangling-pointer crashes.
SymbolStringPtr intern(StringRef S)
Create a symbol string pointer from the given string.
bool empty() const
Returns true if the pool is empty.
~SymbolStringPool()
Destroy a SymbolStringPool.
void clearDeadEntries()
Remove from the pool any entries that are no longer referenced.
Base class for both owning and non-owning symbol-string ptrs.
static bool isRealPoolEntry(PoolEntryPtr P)
friend bool operator!=(SymbolStringPtrBase LHS, SymbolStringPtrBase RHS)
friend bool operator<(SymbolStringPtrBase LHS, SymbolStringPtrBase RHS)
friend bool operator==(SymbolStringPtrBase LHS, SymbolStringPtrBase RHS)
static constexpr uintptr_t InvalidPtrMask
LLVM_ABI friend raw_ostream & operator<<(raw_ostream &OS, const SymbolStringPtrBase &Sym)
static constexpr uintptr_t EmptyBitPattern
static constexpr uintptr_t TombstoneBitPattern
SymbolStringPool::PoolMapEntry PoolEntry
Pointer to a pooled string representing a symbol name.
SymbolStringPtr(const SymbolStringPtr &Other)
SymbolStringPtr & operator=(SymbolStringPtr &&Other)
SymbolStringPtr & operator=(const SymbolStringPtr &Other)
SymbolStringPtr(SymbolStringPtr &&Other)
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
hash_code hash_value(const orc::SymbolStringPtrBase &S)
LLVM_ABI raw_ostream & operator<<(raw_ostream &OS, const SymbolNameSet &Symbols)
Render a SymbolNameSet.
This is an optimization pass for GlobalISel generic memory operations.
@ Other
Any other memory.
Definition ModRef.h:68
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition BitVector.h:869
static orc::NonOwningSymbolStringPtr getEmptyKey()
static bool isEqual(const orc::SymbolStringPtrBase &LHS, const orc::SymbolStringPtrBase &RHS)
static unsigned getHashValue(const orc::SymbolStringPtrBase &V)
static orc::NonOwningSymbolStringPtr getTombstoneKey()
static orc::SymbolStringPtr getEmptyKey()
static bool isEqual(const orc::SymbolStringPtrBase &LHS, const orc::SymbolStringPtrBase &RHS)
static unsigned getHashValue(const orc::SymbolStringPtrBase &V)
static orc::SymbolStringPtr getTombstoneKey()
An information struct used to provide DenseMap with the various necessary components for a given valu...
A traits type that is used to handle pointer types and things that are just wrappers for pointers as ...