blob: 39fa74bf313262f3006b28edca448059048ce7a8 [file] [log] [blame]
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01001//===- SymbolStringPool.h - Multi-threaded pool for JIT symbols -*- C++ -*-===//
2//
Andrew Walbran16937d02019-10-22 13:54:20 +01003// 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
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01006//
7//===----------------------------------------------------------------------===//
8//
9// Contains a multi-threaded string pool suitable for use with ORC.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef LLVM_EXECUTIONENGINE_ORC_SYMBOLSTRINGPOOL_H
14#define LLVM_EXECUTIONENGINE_ORC_SYMBOLSTRINGPOOL_H
15
Andrew Walbran16937d02019-10-22 13:54:20 +010016#include "llvm/ADT/DenseMap.h"
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010017#include "llvm/ADT/StringMap.h"
18#include <atomic>
19#include <mutex>
20
21namespace llvm {
22namespace orc {
23
24class SymbolStringPtr;
25
Andrew Scullcdfcccc2018-10-05 20:58:37 +010026/// String pool for symbol names used by the JIT.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010027class SymbolStringPool {
28 friend class SymbolStringPtr;
29public:
Andrew Scullcdfcccc2018-10-05 20:58:37 +010030 /// Destroy a SymbolStringPool.
31 ~SymbolStringPool();
32
33 /// Create a symbol string pointer from the given string.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010034 SymbolStringPtr intern(StringRef S);
35
Andrew Scullcdfcccc2018-10-05 20:58:37 +010036 /// Remove from the pool any entries that are no longer referenced.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010037 void clearDeadEntries();
38
Andrew Scullcdfcccc2018-10-05 20:58:37 +010039 /// Returns true if the pool is empty.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010040 bool empty() const;
41private:
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
Andrew Scullcdfcccc2018-10-05 20:58:37 +010049/// Pointer to a pooled string representing a symbol name.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010050class SymbolStringPtr {
51 friend class SymbolStringPool;
Andrew Walbran16937d02019-10-22 13:54:20 +010052 friend struct DenseMapInfo<SymbolStringPtr>;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010053 friend bool operator==(const SymbolStringPtr &LHS,
54 const SymbolStringPtr &RHS);
55 friend bool operator<(const SymbolStringPtr &LHS, const SymbolStringPtr &RHS);
56
Andrew Walbran16937d02019-10-22 13:54:20 +010057 static SymbolStringPool::PoolMapEntry Tombstone;
58
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010059public:
60 SymbolStringPtr() = default;
61 SymbolStringPtr(const SymbolStringPtr &Other)
62 : S(Other.S) {
63 if (S)
64 ++S->getValue();
65 }
66
67 SymbolStringPtr& operator=(const SymbolStringPtr &Other) {
68 if (S)
69 --S->getValue();
70 S = Other.S;
71 if (S)
72 ++S->getValue();
73 return *this;
74 }
75
76 SymbolStringPtr(SymbolStringPtr &&Other) : S(nullptr) {
77 std::swap(S, Other.S);
78 }
79
80 SymbolStringPtr& operator=(SymbolStringPtr &&Other) {
81 if (S)
82 --S->getValue();
83 S = nullptr;
84 std::swap(S, Other.S);
85 return *this;
86 }
87
88 ~SymbolStringPtr() {
89 if (S)
90 --S->getValue();
91 }
92
93 StringRef operator*() const { return S->first(); }
94
95private:
96
97 SymbolStringPtr(SymbolStringPool::PoolMapEntry *S)
98 : S(S) {
99 if (S)
100 ++S->getValue();
101 }
102
103 SymbolStringPool::PoolMapEntry *S = nullptr;
104};
105
106inline bool operator==(const SymbolStringPtr &LHS, const SymbolStringPtr &RHS) {
107 return LHS.S == RHS.S;
108}
109
110inline bool operator!=(const SymbolStringPtr &LHS, const SymbolStringPtr &RHS) {
111 return !(LHS == RHS);
112}
113
114inline bool operator<(const SymbolStringPtr &LHS, const SymbolStringPtr &RHS) {
115 return LHS.S < RHS.S;
116}
117
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100118inline SymbolStringPool::~SymbolStringPool() {
119#ifndef NDEBUG
120 clearDeadEntries();
121 assert(Pool.empty() && "Dangling references at pool destruction time");
122#endif // NDEBUG
123}
124
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100125inline SymbolStringPtr SymbolStringPool::intern(StringRef S) {
126 std::lock_guard<std::mutex> Lock(PoolMutex);
127 PoolMap::iterator I;
128 bool Added;
129 std::tie(I, Added) = Pool.try_emplace(S, 0);
130 return SymbolStringPtr(&*I);
131}
132
133inline void SymbolStringPool::clearDeadEntries() {
134 std::lock_guard<std::mutex> Lock(PoolMutex);
135 for (auto I = Pool.begin(), E = Pool.end(); I != E;) {
136 auto Tmp = I++;
137 if (Tmp->second == 0)
138 Pool.erase(Tmp);
139 }
140}
141
142inline bool SymbolStringPool::empty() const {
143 std::lock_guard<std::mutex> Lock(PoolMutex);
144 return Pool.empty();
145}
146
147} // end namespace orc
Andrew Walbran16937d02019-10-22 13:54:20 +0100148
149template <>
150struct DenseMapInfo<orc::SymbolStringPtr> {
151
152 static orc::SymbolStringPtr getEmptyKey() {
153 return orc::SymbolStringPtr();
154 }
155
156 static orc::SymbolStringPtr getTombstoneKey() {
157 return orc::SymbolStringPtr(&orc::SymbolStringPtr::Tombstone);
158 }
159
160 static unsigned getHashValue(orc::SymbolStringPtr V) {
161 uintptr_t IV = reinterpret_cast<uintptr_t>(V.S);
162 return unsigned(IV) ^ unsigned(IV >> 9);
163 }
164
165 static bool isEqual(const orc::SymbolStringPtr &LHS,
166 const orc::SymbolStringPtr &RHS) {
167 return LHS.S == RHS.S;
168 }
169};
170
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100171} // end namespace llvm
172
173#endif // LLVM_EXECUTIONENGINE_ORC_SYMBOLSTRINGPOOL_H