1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 | //===- SymbolStringPool.h - Multi-threaded pool for JIT symbols -*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // Contains a multi-threaded string pool suitable for use with ORC. // //===----------------------------------------------------------------------===// #ifndef LLVM_EXECUTIONENGINE_ORC_SYMBOLSTRINGPOOL_H #define LLVM_EXECUTIONENGINE_ORC_SYMBOLSTRINGPOOL_H #include "llvm/ADT/StringMap.h" #include <atomic> #include <mutex> namespace llvm { namespace orc { class SymbolStringPtr; /// @brief String pool for symbol names used by the JIT. class SymbolStringPool { friend class SymbolStringPtr; public: /// @brief Create a symbol string pointer from the given string. SymbolStringPtr intern(StringRef S); /// @brief Remove from the pool any entries that are no longer referenced. void clearDeadEntries(); /// @brief Returns true if the pool is empty. bool empty() const; private: using RefCountType = std::atomic<uint64_t>; using PoolMap = StringMap<RefCountType>; using PoolMapEntry = StringMapEntry<RefCountType>; mutable std::mutex PoolMutex; PoolMap Pool; }; /// @brief Pointer to a pooled string representing a symbol name. class SymbolStringPtr { friend class SymbolStringPool; public: SymbolStringPtr() = default; SymbolStringPtr(const SymbolStringPtr &Other) : S(Other.S) { if (S) ++S->getValue(); } SymbolStringPtr& operator=(const SymbolStringPtr &Other) { if (S) --S->getValue(); S = Other.S; if (S) ++S->getValue(); return *this; } SymbolStringPtr(SymbolStringPtr &&Other) : S(nullptr) { std::swap(S, Other.S); } SymbolStringPtr& operator=(SymbolStringPtr &&Other) { if (S) --S->getValue(); S = nullptr; std::swap(S, Other.S); return *this; } ~SymbolStringPtr() { if (S) --S->getValue(); } bool operator==(const SymbolStringPtr &Other) const { return S == Other.S; } bool operator!=(const SymbolStringPtr &Other) const { return !(*this == Other); } bool operator<(const SymbolStringPtr &Other) const { return S->getValue() < Other.S->getValue(); } private: SymbolStringPtr(SymbolStringPool::PoolMapEntry *S) : S(S) { if (S) ++S->getValue(); } SymbolStringPool::PoolMapEntry *S = nullptr; }; inline SymbolStringPtr SymbolStringPool::intern(StringRef S) { std::lock_guard<std::mutex> Lock(PoolMutex); auto I = Pool.find(S); if (I != Pool.end()) return SymbolStringPtr(&*I); bool Added; std::tie(I, Added) = Pool.try_emplace(S, 0); assert(Added && "Insert should always succeed here"); return SymbolStringPtr(&*I); } inline void SymbolStringPool::clearDeadEntries() { std::lock_guard<std::mutex> Lock(PoolMutex); for (auto I = Pool.begin(), E = Pool.end(); I != E;) { auto Tmp = std::next(I); if (I->second == 0) Pool.erase(I); I = Tmp; } } inline bool SymbolStringPool::empty() const { std::lock_guard<std::mutex> Lock(PoolMutex); return Pool.empty(); } } // end namespace orc } // end namespace llvm #endif // LLVM_EXECUTIONENGINE_ORC_SYMBOLSTRINGPOOL_H |