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