1 //===- SymbolStringPool.h - Multi-threaded pool for JIT symbols -*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
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"
24 class SymbolStringPtr
;
26 /// String pool for symbol names used by the JIT.
27 class SymbolStringPool
{
28 friend class SymbolStringPtr
;
30 /// Destroy a 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.
42 using RefCountType
= std::atomic
<size_t>;
43 using PoolMap
= StringMap
<RefCountType
>;
44 using PoolMapEntry
= StringMapEntry
<RefCountType
>;
45 mutable std::mutex PoolMutex
;
49 /// Pointer to a pooled string representing a symbol name.
50 class SymbolStringPtr
{
51 friend class SymbolStringPool
;
52 friend struct DenseMapInfo
<SymbolStringPtr
>;
55 SymbolStringPtr() = default;
56 SymbolStringPtr(const SymbolStringPtr
&Other
)
58 if (isRealPoolEntry(S
))
62 SymbolStringPtr
& operator=(const SymbolStringPtr
&Other
) {
63 if (isRealPoolEntry(S
))
66 if (isRealPoolEntry(S
))
71 SymbolStringPtr(SymbolStringPtr
&&Other
) : S(nullptr) {
72 std::swap(S
, Other
.S
);
75 SymbolStringPtr
& operator=(SymbolStringPtr
&&Other
) {
76 if (isRealPoolEntry(S
))
79 std::swap(S
, Other
.S
);
84 if (isRealPoolEntry(S
))
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
) {
100 friend bool operator<(const SymbolStringPtr
&LHS
,
101 const SymbolStringPtr
&RHS
) {
102 return LHS
.S
< RHS
.S
;
106 using PoolEntryPtr
= SymbolStringPool::PoolMapEntry
*;
108 SymbolStringPtr(SymbolStringPool::PoolMapEntry
*S
)
110 if (isRealPoolEntry(S
))
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
) !=
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() {
146 assert(Pool
.empty() && "Dangling references at pool destruction time");
150 inline SymbolStringPtr
SymbolStringPool::intern(StringRef S
) {
151 std::lock_guard
<std::mutex
> Lock(PoolMutex
);
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
;) {
162 if (Tmp
->second
== 0)
167 inline bool SymbolStringPool::empty() const {
168 std::lock_guard
<std::mutex
> Lock(PoolMutex
);
172 } // end namespace orc
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