SymbolStringPool.h 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. //===- SymbolStringPool.h - Multi-threaded 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 multi-threaded string pool suitable for use with ORC.
  10. //
  11. //===----------------------------------------------------------------------===//
  12. #ifndef LLVM_EXECUTIONENGINE_ORC_SYMBOLSTRINGPOOL_H
  13. #define LLVM_EXECUTIONENGINE_ORC_SYMBOLSTRINGPOOL_H
  14. #include "llvm/ADT/DenseMap.h"
  15. #include "llvm/ADT/StringMap.h"
  16. #include <atomic>
  17. #include <mutex>
  18. namespace llvm {
  19. namespace orc {
  20. class SymbolStringPtr;
  21. /// String pool for symbol names used by the JIT.
  22. class SymbolStringPool {
  23. friend class SymbolStringPtr;
  24. public:
  25. /// Destroy a SymbolStringPool.
  26. ~SymbolStringPool();
  27. /// Create a symbol string pointer from the given string.
  28. SymbolStringPtr intern(StringRef S);
  29. /// Remove from the pool any entries that are no longer referenced.
  30. void clearDeadEntries();
  31. /// Returns true if the pool is empty.
  32. bool empty() const;
  33. private:
  34. using RefCountType = std::atomic<size_t>;
  35. using PoolMap = StringMap<RefCountType>;
  36. using PoolMapEntry = StringMapEntry<RefCountType>;
  37. mutable std::mutex PoolMutex;
  38. PoolMap Pool;
  39. };
  40. /// Pointer to a pooled string representing a symbol name.
  41. class SymbolStringPtr {
  42. friend class OrcV2CAPIHelper;
  43. friend class SymbolStringPool;
  44. friend struct DenseMapInfo<SymbolStringPtr>;
  45. public:
  46. SymbolStringPtr() = default;
  47. SymbolStringPtr(std::nullptr_t) {}
  48. SymbolStringPtr(const SymbolStringPtr &Other)
  49. : S(Other.S) {
  50. if (isRealPoolEntry(S))
  51. ++S->getValue();
  52. }
  53. SymbolStringPtr& operator=(const SymbolStringPtr &Other) {
  54. if (isRealPoolEntry(S)) {
  55. assert(S->getValue() && "Releasing SymbolStringPtr with zero ref count");
  56. --S->getValue();
  57. }
  58. S = Other.S;
  59. if (isRealPoolEntry(S))
  60. ++S->getValue();
  61. return *this;
  62. }
  63. SymbolStringPtr(SymbolStringPtr &&Other) : S(nullptr) {
  64. std::swap(S, Other.S);
  65. }
  66. SymbolStringPtr& operator=(SymbolStringPtr &&Other) {
  67. if (isRealPoolEntry(S)) {
  68. assert(S->getValue() && "Releasing SymbolStringPtr with zero ref count");
  69. --S->getValue();
  70. }
  71. S = nullptr;
  72. std::swap(S, Other.S);
  73. return *this;
  74. }
  75. ~SymbolStringPtr() {
  76. if (isRealPoolEntry(S)) {
  77. assert(S->getValue() && "Releasing SymbolStringPtr with zero ref count");
  78. --S->getValue();
  79. }
  80. }
  81. explicit operator bool() const { return S; }
  82. StringRef operator*() const { return S->first(); }
  83. friend bool operator==(const SymbolStringPtr &LHS,
  84. const SymbolStringPtr &RHS) {
  85. return LHS.S == RHS.S;
  86. }
  87. friend bool operator!=(const SymbolStringPtr &LHS,
  88. const SymbolStringPtr &RHS) {
  89. return !(LHS == RHS);
  90. }
  91. friend bool operator<(const SymbolStringPtr &LHS,
  92. const SymbolStringPtr &RHS) {
  93. return LHS.S < RHS.S;
  94. }
  95. private:
  96. using PoolEntry = SymbolStringPool::PoolMapEntry;
  97. using PoolEntryPtr = PoolEntry *;
  98. SymbolStringPtr(SymbolStringPool::PoolMapEntry *S)
  99. : S(S) {
  100. if (isRealPoolEntry(S))
  101. ++S->getValue();
  102. }
  103. // Returns false for null, empty, and tombstone values, true otherwise.
  104. bool isRealPoolEntry(PoolEntryPtr P) {
  105. return ((reinterpret_cast<uintptr_t>(P) - 1) & InvalidPtrMask) !=
  106. InvalidPtrMask;
  107. }
  108. static SymbolStringPtr getEmptyVal() {
  109. return SymbolStringPtr(reinterpret_cast<PoolEntryPtr>(EmptyBitPattern));
  110. }
  111. static SymbolStringPtr getTombstoneVal() {
  112. return SymbolStringPtr(reinterpret_cast<PoolEntryPtr>(TombstoneBitPattern));
  113. }
  114. constexpr static uintptr_t EmptyBitPattern =
  115. std::numeric_limits<uintptr_t>::max()
  116. << PointerLikeTypeTraits<PoolEntryPtr>::NumLowBitsAvailable;
  117. constexpr static uintptr_t TombstoneBitPattern =
  118. (std::numeric_limits<uintptr_t>::max() - 1)
  119. << PointerLikeTypeTraits<PoolEntryPtr>::NumLowBitsAvailable;
  120. constexpr static uintptr_t InvalidPtrMask =
  121. (std::numeric_limits<uintptr_t>::max() - 3)
  122. << PointerLikeTypeTraits<PoolEntryPtr>::NumLowBitsAvailable;
  123. PoolEntryPtr S = nullptr;
  124. };
  125. inline SymbolStringPool::~SymbolStringPool() {
  126. #ifndef NDEBUG
  127. clearDeadEntries();
  128. assert(Pool.empty() && "Dangling references at pool destruction time");
  129. #endif // NDEBUG
  130. }
  131. inline SymbolStringPtr SymbolStringPool::intern(StringRef S) {
  132. std::lock_guard<std::mutex> Lock(PoolMutex);
  133. PoolMap::iterator I;
  134. bool Added;
  135. std::tie(I, Added) = Pool.try_emplace(S, 0);
  136. return SymbolStringPtr(&*I);
  137. }
  138. inline void SymbolStringPool::clearDeadEntries() {
  139. std::lock_guard<std::mutex> Lock(PoolMutex);
  140. for (auto I = Pool.begin(), E = Pool.end(); I != E;) {
  141. auto Tmp = I++;
  142. if (Tmp->second == 0)
  143. Pool.erase(Tmp);
  144. }
  145. }
  146. inline bool SymbolStringPool::empty() const {
  147. std::lock_guard<std::mutex> Lock(PoolMutex);
  148. return Pool.empty();
  149. }
  150. } // end namespace orc
  151. template <>
  152. struct DenseMapInfo<orc::SymbolStringPtr> {
  153. static orc::SymbolStringPtr getEmptyKey() {
  154. return orc::SymbolStringPtr::getEmptyVal();
  155. }
  156. static orc::SymbolStringPtr getTombstoneKey() {
  157. return orc::SymbolStringPtr::getTombstoneVal();
  158. }
  159. static unsigned getHashValue(const orc::SymbolStringPtr &V) {
  160. return DenseMapInfo<orc::SymbolStringPtr::PoolEntryPtr>::getHashValue(V.S);
  161. }
  162. static bool isEqual(const orc::SymbolStringPtr &LHS,
  163. const orc::SymbolStringPtr &RHS) {
  164. return LHS.S == RHS.S;
  165. }
  166. };
  167. } // end namespace llvm
  168. #endif // LLVM_EXECUTIONENGINE_ORC_SYMBOLSTRINGPOOL_H