blob: 4c45cfd199dd21c5982003d86d67a5b9a2f022dd [file] [log] [blame]
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01001//===- 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
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;
52 friend bool operator==(const SymbolStringPtr &LHS,
53 const SymbolStringPtr &RHS);
54 friend bool operator<(const SymbolStringPtr &LHS, const SymbolStringPtr &RHS);
55
56public:
57 SymbolStringPtr() = default;
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
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
85 ~SymbolStringPtr() {
86 if (S)
87 --S->getValue();
88 }
89
90 StringRef operator*() const { return S->first(); }
91
92private:
93
94 SymbolStringPtr(SymbolStringPool::PoolMapEntry *S)
95 : S(S) {
96 if (S)
97 ++S->getValue();
98 }
99
100 SymbolStringPool::PoolMapEntry *S = nullptr;
101};
102
103inline bool operator==(const SymbolStringPtr &LHS, const SymbolStringPtr &RHS) {
104 return LHS.S == RHS.S;
105}
106
107inline bool operator!=(const SymbolStringPtr &LHS, const SymbolStringPtr &RHS) {
108 return !(LHS == RHS);
109}
110
111inline bool operator<(const SymbolStringPtr &LHS, const SymbolStringPtr &RHS) {
112 return LHS.S < RHS.S;
113}
114
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100115inline SymbolStringPool::~SymbolStringPool() {
116#ifndef NDEBUG
117 clearDeadEntries();
118 assert(Pool.empty() && "Dangling references at pool destruction time");
119#endif // NDEBUG
120}
121
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100122inline 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
130inline 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
139inline 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