File indexing completed on 2026-05-10 08:43:54
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #ifndef LLVM_EXECUTIONENGINE_ORC_SYMBOLSTRINGPOOL_H
0014 #define LLVM_EXECUTIONENGINE_ORC_SYMBOLSTRINGPOOL_H
0015
0016 #include "llvm/ADT/DenseMap.h"
0017 #include "llvm/ADT/StringMap.h"
0018 #include <atomic>
0019 #include <mutex>
0020
0021 namespace llvm {
0022
0023 class raw_ostream;
0024
0025 namespace orc {
0026
0027 class SymbolStringPtrBase;
0028 class SymbolStringPtr;
0029 class NonOwningSymbolStringPtr;
0030
0031
0032 class SymbolStringPool {
0033 friend class SymbolStringPoolTest;
0034 friend class SymbolStringPtrBase;
0035 friend class SymbolStringPoolEntryUnsafe;
0036
0037
0038 friend raw_ostream &operator<<(raw_ostream &OS, const SymbolStringPool &SSP);
0039
0040 public:
0041
0042 ~SymbolStringPool();
0043
0044
0045 SymbolStringPtr intern(StringRef S);
0046
0047
0048 void clearDeadEntries();
0049
0050
0051 bool empty() const;
0052
0053 private:
0054 size_t getRefCount(const SymbolStringPtrBase &S) const;
0055
0056 using RefCountType = std::atomic<size_t>;
0057 using PoolMap = StringMap<RefCountType>;
0058 using PoolMapEntry = StringMapEntry<RefCountType>;
0059 mutable std::mutex PoolMutex;
0060 PoolMap Pool;
0061 };
0062
0063
0064
0065
0066
0067
0068
0069
0070 class SymbolStringPtrBase {
0071 friend class SymbolStringPool;
0072 friend struct DenseMapInfo<SymbolStringPtr>;
0073 friend struct DenseMapInfo<NonOwningSymbolStringPtr>;
0074
0075 public:
0076 SymbolStringPtrBase() = default;
0077 SymbolStringPtrBase(std::nullptr_t) {}
0078
0079 explicit operator bool() const { return S; }
0080
0081 StringRef operator*() const { return S->first(); }
0082
0083 friend bool operator==(SymbolStringPtrBase LHS, SymbolStringPtrBase RHS) {
0084 return LHS.S == RHS.S;
0085 }
0086
0087 friend bool operator!=(SymbolStringPtrBase LHS, SymbolStringPtrBase RHS) {
0088 return !(LHS == RHS);
0089 }
0090
0091 friend bool operator<(SymbolStringPtrBase LHS, SymbolStringPtrBase RHS) {
0092 return LHS.S < RHS.S;
0093 }
0094
0095 friend raw_ostream &operator<<(raw_ostream &OS,
0096 const SymbolStringPtrBase &Sym);
0097
0098 #ifndef NDEBUG
0099
0100
0101
0102
0103 bool poolEntryIsAlive() const {
0104 return isRealPoolEntry(S) ? S->getValue() != 0 : true;
0105 }
0106 #endif
0107
0108 protected:
0109 using PoolEntry = SymbolStringPool::PoolMapEntry;
0110 using PoolEntryPtr = PoolEntry *;
0111
0112 SymbolStringPtrBase(PoolEntryPtr S) : S(S) {}
0113
0114 constexpr static uintptr_t EmptyBitPattern =
0115 std::numeric_limits<uintptr_t>::max()
0116 << PointerLikeTypeTraits<PoolEntryPtr>::NumLowBitsAvailable;
0117
0118 constexpr static uintptr_t TombstoneBitPattern =
0119 (std::numeric_limits<uintptr_t>::max() - 1)
0120 << PointerLikeTypeTraits<PoolEntryPtr>::NumLowBitsAvailable;
0121
0122 constexpr static uintptr_t InvalidPtrMask =
0123 (std::numeric_limits<uintptr_t>::max() - 3)
0124 << PointerLikeTypeTraits<PoolEntryPtr>::NumLowBitsAvailable;
0125
0126
0127 static bool isRealPoolEntry(PoolEntryPtr P) {
0128 return ((reinterpret_cast<uintptr_t>(P) - 1) & InvalidPtrMask) !=
0129 InvalidPtrMask;
0130 }
0131
0132 size_t getRefCount() const {
0133 return isRealPoolEntry(S) ? size_t(S->getValue()) : size_t(0);
0134 }
0135
0136 PoolEntryPtr S = nullptr;
0137 };
0138
0139
0140 class SymbolStringPtr : public SymbolStringPtrBase {
0141 friend class SymbolStringPool;
0142 friend class SymbolStringPoolEntryUnsafe;
0143 friend struct DenseMapInfo<SymbolStringPtr>;
0144
0145 public:
0146 SymbolStringPtr() = default;
0147 SymbolStringPtr(std::nullptr_t) {}
0148 SymbolStringPtr(const SymbolStringPtr &Other) : SymbolStringPtrBase(Other.S) {
0149 incRef();
0150 }
0151
0152 explicit SymbolStringPtr(NonOwningSymbolStringPtr Other);
0153
0154 SymbolStringPtr& operator=(const SymbolStringPtr &Other) {
0155 decRef();
0156 S = Other.S;
0157 incRef();
0158 return *this;
0159 }
0160
0161 SymbolStringPtr(SymbolStringPtr &&Other) { std::swap(S, Other.S); }
0162
0163 SymbolStringPtr& operator=(SymbolStringPtr &&Other) {
0164 decRef();
0165 S = nullptr;
0166 std::swap(S, Other.S);
0167 return *this;
0168 }
0169
0170 ~SymbolStringPtr() { decRef(); }
0171
0172 private:
0173 SymbolStringPtr(PoolEntryPtr S) : SymbolStringPtrBase(S) { incRef(); }
0174
0175 void incRef() {
0176 if (isRealPoolEntry(S))
0177 ++S->getValue();
0178 }
0179
0180 void decRef() {
0181 if (isRealPoolEntry(S)) {
0182 assert(S->getValue() && "Releasing SymbolStringPtr with zero ref count");
0183 --S->getValue();
0184 }
0185 }
0186
0187 static SymbolStringPtr getEmptyVal() {
0188 return SymbolStringPtr(reinterpret_cast<PoolEntryPtr>(EmptyBitPattern));
0189 }
0190
0191 static SymbolStringPtr getTombstoneVal() {
0192 return SymbolStringPtr(reinterpret_cast<PoolEntryPtr>(TombstoneBitPattern));
0193 }
0194 };
0195
0196
0197
0198 class SymbolStringPoolEntryUnsafe {
0199 public:
0200 using PoolEntry = SymbolStringPool::PoolMapEntry;
0201
0202 SymbolStringPoolEntryUnsafe(PoolEntry *E) : E(E) {}
0203
0204
0205 static SymbolStringPoolEntryUnsafe from(const SymbolStringPtr &S) {
0206 return S.S;
0207 }
0208
0209
0210 static SymbolStringPoolEntryUnsafe take(SymbolStringPtr &&S) {
0211 PoolEntry *E = nullptr;
0212 std::swap(E, S.S);
0213 return E;
0214 }
0215
0216 PoolEntry *rawPtr() { return E; }
0217
0218
0219
0220 SymbolStringPtr copyToSymbolStringPtr() { return SymbolStringPtr(E); }
0221
0222
0223
0224 SymbolStringPtr moveToSymbolStringPtr() {
0225 SymbolStringPtr S;
0226 std::swap(S.S, E);
0227 return S;
0228 }
0229
0230 void retain() { ++E->getValue(); }
0231 void release() { --E->getValue(); }
0232
0233 private:
0234 PoolEntry *E = nullptr;
0235 };
0236
0237
0238
0239
0240
0241
0242
0243
0244
0245
0246
0247
0248
0249 class NonOwningSymbolStringPtr : public SymbolStringPtrBase {
0250 friend struct DenseMapInfo<orc::NonOwningSymbolStringPtr>;
0251
0252 public:
0253 NonOwningSymbolStringPtr() = default;
0254 explicit NonOwningSymbolStringPtr(const SymbolStringPtr &S)
0255 : SymbolStringPtrBase(S) {}
0256
0257 using SymbolStringPtrBase::operator=;
0258
0259 private:
0260 NonOwningSymbolStringPtr(PoolEntryPtr S) : SymbolStringPtrBase(S) {}
0261
0262 static NonOwningSymbolStringPtr getEmptyVal() {
0263 return NonOwningSymbolStringPtr(
0264 reinterpret_cast<PoolEntryPtr>(EmptyBitPattern));
0265 }
0266
0267 static NonOwningSymbolStringPtr getTombstoneVal() {
0268 return NonOwningSymbolStringPtr(
0269 reinterpret_cast<PoolEntryPtr>(TombstoneBitPattern));
0270 }
0271 };
0272
0273 inline SymbolStringPtr::SymbolStringPtr(NonOwningSymbolStringPtr Other)
0274 : SymbolStringPtrBase(Other) {
0275 assert(poolEntryIsAlive() &&
0276 "SymbolStringPtr constructed from invalid non-owning pointer.");
0277
0278 if (isRealPoolEntry(S))
0279 ++S->getValue();
0280 }
0281
0282 inline SymbolStringPool::~SymbolStringPool() {
0283 #ifndef NDEBUG
0284 clearDeadEntries();
0285 assert(Pool.empty() && "Dangling references at pool destruction time");
0286 #endif
0287 }
0288
0289 inline SymbolStringPtr SymbolStringPool::intern(StringRef S) {
0290 std::lock_guard<std::mutex> Lock(PoolMutex);
0291 PoolMap::iterator I;
0292 bool Added;
0293 std::tie(I, Added) = Pool.try_emplace(S, 0);
0294 return SymbolStringPtr(&*I);
0295 }
0296
0297 inline void SymbolStringPool::clearDeadEntries() {
0298 std::lock_guard<std::mutex> Lock(PoolMutex);
0299 for (auto I = Pool.begin(), E = Pool.end(); I != E;) {
0300 auto Tmp = I++;
0301 if (Tmp->second == 0)
0302 Pool.erase(Tmp);
0303 }
0304 }
0305
0306 inline bool SymbolStringPool::empty() const {
0307 std::lock_guard<std::mutex> Lock(PoolMutex);
0308 return Pool.empty();
0309 }
0310
0311 inline size_t
0312 SymbolStringPool::getRefCount(const SymbolStringPtrBase &S) const {
0313 return S.getRefCount();
0314 }
0315
0316 }
0317
0318 template <>
0319 struct DenseMapInfo<orc::SymbolStringPtr> {
0320
0321 static orc::SymbolStringPtr getEmptyKey() {
0322 return orc::SymbolStringPtr::getEmptyVal();
0323 }
0324
0325 static orc::SymbolStringPtr getTombstoneKey() {
0326 return orc::SymbolStringPtr::getTombstoneVal();
0327 }
0328
0329 static unsigned getHashValue(const orc::SymbolStringPtrBase &V) {
0330 return DenseMapInfo<orc::SymbolStringPtr::PoolEntryPtr>::getHashValue(V.S);
0331 }
0332
0333 static bool isEqual(const orc::SymbolStringPtrBase &LHS,
0334 const orc::SymbolStringPtrBase &RHS) {
0335 return LHS.S == RHS.S;
0336 }
0337 };
0338
0339 template <> struct DenseMapInfo<orc::NonOwningSymbolStringPtr> {
0340
0341 static orc::NonOwningSymbolStringPtr getEmptyKey() {
0342 return orc::NonOwningSymbolStringPtr::getEmptyVal();
0343 }
0344
0345 static orc::NonOwningSymbolStringPtr getTombstoneKey() {
0346 return orc::NonOwningSymbolStringPtr::getTombstoneVal();
0347 }
0348
0349 static unsigned getHashValue(const orc::SymbolStringPtrBase &V) {
0350 return DenseMapInfo<
0351 orc::NonOwningSymbolStringPtr::PoolEntryPtr>::getHashValue(V.S);
0352 }
0353
0354 static bool isEqual(const orc::SymbolStringPtrBase &LHS,
0355 const orc::SymbolStringPtrBase &RHS) {
0356 return LHS.S == RHS.S;
0357 }
0358 };
0359
0360 }
0361
0362 #endif