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