LLVM 20.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/StringMap.h"
18#include <atomic>
19#include <mutex>
20
21namespace llvm {
22
23class raw_ostream;
24
25namespace orc {
26
27class SymbolStringPtrBase;
28class SymbolStringPtr;
29class NonOwningSymbolStringPtr;
30
31/// String pool for symbol names used by the JIT.
34 friend class SymbolStringPtrBase;
36
37 // Implemented in DebugUtils.h.
39
40public:
41 /// Destroy a SymbolStringPool.
43
44 /// Create a symbol string pointer from the given string.
46
47 /// Remove from the pool any entries that are no longer referenced.
48 void clearDeadEntries();
49
50 /// Returns true if the pool is empty.
51 bool empty() const;
52
53private:
54 size_t getRefCount(const SymbolStringPtrBase &S) const;
55
56 using RefCountType = std::atomic<size_t>;
59 mutable std::mutex PoolMutex;
60 PoolMap Pool;
61};
62
63/// Base class for both owning and non-owning symbol-string ptrs.
64///
65/// All symbol-string ptrs are convertible to bool, dereferenceable and
66/// comparable.
67///
68/// SymbolStringPtrBases are default-constructible and constructible
69/// from nullptr to enable comparison with these values.
71 friend class SymbolStringPool;
72 friend struct DenseMapInfo<SymbolStringPtr>;
74
75public:
77 SymbolStringPtrBase(std::nullptr_t) {}
78
79 explicit operator bool() const { return S; }
80
81 StringRef operator*() const { return S->first(); }
82
84 return LHS.S == RHS.S;
85 }
86
88 return !(LHS == RHS);
89 }
90
92 return LHS.S < RHS.S;
93 }
94
97
98#ifndef NDEBUG
99 // Returns true if the pool entry's ref count is above zero (or if the entry
100 // is an empty or tombstone value). Useful for debugging and testing -- this
101 // method can be used to identify SymbolStringPtrs and
102 // NonOwningSymbolStringPtrs that are pointing to abandoned pool entries.
103 bool poolEntryIsAlive() const {
104 return isRealPoolEntry(S) ? S->getValue() != 0 : true;
105 }
106#endif
107
108protected:
111
113
114 constexpr static uintptr_t EmptyBitPattern =
115 std::numeric_limits<uintptr_t>::max()
117
118 constexpr static uintptr_t TombstoneBitPattern =
119 (std::numeric_limits<uintptr_t>::max() - 1)
121
122 constexpr static uintptr_t InvalidPtrMask =
123 (std::numeric_limits<uintptr_t>::max() - 3)
125
126 // Returns false for null, empty, and tombstone values, true otherwise.
128 return ((reinterpret_cast<uintptr_t>(P) - 1) & InvalidPtrMask) !=
130 }
131
132 size_t getRefCount() const {
133 return isRealPoolEntry(S) ? size_t(S->getValue()) : size_t(0);
134 }
135
136 PoolEntryPtr S = nullptr;
137};
138
139/// Pointer to a pooled string representing a symbol name.
141 friend class SymbolStringPool;
143 friend struct DenseMapInfo<SymbolStringPtr>;
144
145public:
146 SymbolStringPtr() = default;
147 SymbolStringPtr(std::nullptr_t) {}
149 incRef();
150 }
151
153
155 decRef();
156 S = Other.S;
157 incRef();
158 return *this;
159 }
160
162
164 decRef();
165 S = nullptr;
166 std::swap(S, Other.S);
167 return *this;
168 }
169
170 ~SymbolStringPtr() { decRef(); }
171
172private:
174
175 void incRef() {
176 if (isRealPoolEntry(S))
177 ++S->getValue();
178 }
179
180 void decRef() {
181 if (isRealPoolEntry(S)) {
182 assert(S->getValue() && "Releasing SymbolStringPtr with zero ref count");
183 --S->getValue();
184 }
185 }
186
187 static SymbolStringPtr getEmptyVal() {
188 return SymbolStringPtr(reinterpret_cast<PoolEntryPtr>(EmptyBitPattern));
189 }
190
191 static SymbolStringPtr getTombstoneVal() {
192 return SymbolStringPtr(reinterpret_cast<PoolEntryPtr>(TombstoneBitPattern));
193 }
194};
195
196/// Provides unsafe access to ownership operations on SymbolStringPtr.
197/// This class can be used to manage SymbolStringPtr instances from C.
199public:
201
203
204 /// Create an unsafe pool entry ref without changing the ref-count.
206 return S.S;
207 }
208
209 /// Consumes the given SymbolStringPtr without releasing the pool entry.
211 PoolEntry *E = nullptr;
212 std::swap(E, S.S);
213 return E;
214 }
215
216 PoolEntry *rawPtr() { return E; }
217
218 /// Creates a SymbolStringPtr for this entry, with the SymbolStringPtr
219 /// retaining the entry as usual.
221
222 /// Creates a SymbolStringPtr for this entry *without* performing a retain
223 /// operation during construction.
226 std::swap(S.S, E);
227 return S;
228 }
229
230 void retain() { ++E->getValue(); }
231 void release() { --E->getValue(); }
232
233private:
234 PoolEntry *E = nullptr;
235};
236
237/// Non-owning SymbolStringPool entry pointer. Instances are comparable with
238/// SymbolStringPtr instances and guaranteed to have the same hash, but do not
239/// affect the ref-count of the pooled string (and are therefore cheaper to
240/// copy).
241///
242/// NonOwningSymbolStringPtrs are silently invalidated if the pool entry's
243/// ref-count drops to zero, so they should only be used in contexts where a
244/// corresponding SymbolStringPtr is known to exist (which will guarantee that
245/// the ref-count stays above zero). E.g. in a graph where nodes are
246/// represented by SymbolStringPtrs the edges can be represented by pairs of
247/// NonOwningSymbolStringPtrs and this will make the introduction of deletion
248/// of edges cheaper.
250 friend struct DenseMapInfo<orc::NonOwningSymbolStringPtr>;
251
252public:
254 explicit NonOwningSymbolStringPtr(const SymbolStringPtr &S)
255 : SymbolStringPtrBase(S) {}
256
257 using SymbolStringPtrBase::operator=;
258
259private:
261
262 static NonOwningSymbolStringPtr getEmptyVal() {
264 reinterpret_cast<PoolEntryPtr>(EmptyBitPattern));
265 }
266
267 static NonOwningSymbolStringPtr getTombstoneVal() {
269 reinterpret_cast<PoolEntryPtr>(TombstoneBitPattern));
270 }
271};
272
276 "SymbolStringPtr constructed from invalid non-owning pointer.");
277
278 if (isRealPoolEntry(S))
279 ++S->getValue();
280}
281
283#ifndef NDEBUG
285 assert(Pool.empty() && "Dangling references at pool destruction time");
286#endif // NDEBUG
287}
288
290 std::lock_guard<std::mutex> Lock(PoolMutex);
292 bool Added;
293 std::tie(I, Added) = Pool.try_emplace(S, 0);
294 return SymbolStringPtr(&*I);
295}
296
298 std::lock_guard<std::mutex> Lock(PoolMutex);
299 for (auto I = Pool.begin(), E = Pool.end(); I != E;) {
300 auto Tmp = I++;
301 if (Tmp->second == 0)
302 Pool.erase(Tmp);
303 }
304}
305
306inline bool SymbolStringPool::empty() const {
307 std::lock_guard<std::mutex> Lock(PoolMutex);
308 return Pool.empty();
309}
310
311inline size_t
312SymbolStringPool::getRefCount(const SymbolStringPtrBase &S) const {
313 return S.getRefCount();
314}
315
316} // end namespace orc
317
318template <>
319struct DenseMapInfo<orc::SymbolStringPtr> {
320
322 return orc::SymbolStringPtr::getEmptyVal();
323 }
324
326 return orc::SymbolStringPtr::getTombstoneVal();
327 }
328
329 static unsigned getHashValue(const orc::SymbolStringPtrBase &V) {
331 }
332
335 return LHS.S == RHS.S;
336 }
337};
338
339template <> struct DenseMapInfo<orc::NonOwningSymbolStringPtr> {
340
342 return orc::NonOwningSymbolStringPtr::getEmptyVal();
343 }
344
346 return orc::NonOwningSymbolStringPtr::getTombstoneVal();
347 }
348
349 static unsigned getHashValue(const orc::SymbolStringPtrBase &V) {
350 return DenseMapInfo<
352 }
353
356 return LHS.S == RHS.S;
357 }
358};
359
360} // end namespace llvm
361
362#endif // LLVM_EXECUTIONENGINE_ORC_SYMBOLSTRINGPOOL_H
This file defines the StringMap class.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file defines the DenseMap class.
Symbol * Sym
Definition: ELF_riscv.cpp:479
#define I(x, y, z)
Definition: MD5.cpp:58
#define P(N)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
raw_pwrite_stream & OS
Value * RHS
Value * LHS
const ValueTy & getValue() const
StringMapEntry - This is used to represent one value that is inserted into a StringMap.
StringRef first() const
bool empty() const
Definition: StringMap.h:103
iterator end()
Definition: StringMap.h:220
iterator begin()
Definition: StringMap.h:219
void erase(iterator I)
Definition: StringMap.h:416
std::pair< iterator, bool > try_emplace(StringRef Key, ArgsTy &&...Args)
Emplace a new element for the specified key into the map if the key isn't already in the map.
Definition: StringMap.h:368
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:51
Non-owning SymbolStringPool entry pointer.
Provides unsafe access to ownership operations on SymbolStringPtr.
static SymbolStringPoolEntryUnsafe from(const SymbolStringPtr &S)
Create an unsafe pool entry ref without changing the ref-count.
SymbolStringPtr copyToSymbolStringPtr()
Creates a SymbolStringPtr for this entry, with the SymbolStringPtr retaining the entry as usual.
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.
friend raw_ostream & operator<<(raw_ostream &OS, const SymbolStringPool &SSP)
Dump a SymbolStringPool. Useful for debugging dangling-pointer crashes.
Definition: DebugUtils.cpp:294
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.
friend raw_ostream & operator<<(raw_ostream &OS, const SymbolStringPtrBase &Sym)
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
static constexpr uintptr_t EmptyBitPattern
static constexpr uintptr_t TombstoneBitPattern
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:52
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Other
Any other memory.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition: BitVector.h:860
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...
Definition: DenseMapInfo.h:52
A traits type that is used to handle pointer types and things that are just wrappers for pointers as ...