SymbolStringPool.h 5.6 KB

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