Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
14 pmbaty 1
//===-- SymbolStringPool.h -- Thread-safe pool for JIT symbols --*- C++ -*-===//
2
//
3
// 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
6
//
7
//===----------------------------------------------------------------------===//
8
//
9
// Contains a thread-safe 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
 
16
#include "llvm/ADT/DenseMap.h"
17
#include "llvm/ADT/StringMap.h"
18
#include <atomic>
19
#include <mutex>
20
 
21
namespace llvm {
22
 
23
class raw_ostream;
24
 
25
namespace orc {
26
 
27
class SymbolStringPtr;
28
 
29
/// String pool for symbol names used by the JIT.
30
class SymbolStringPool {
31
  friend class SymbolStringPtr;
32
 
33
  // Implemented in DebugUtils.h.
34
  friend raw_ostream &operator<<(raw_ostream &OS, const SymbolStringPool &SSP);
35
 
36
public:
37
  /// Destroy a SymbolStringPool.
38
  ~SymbolStringPool();
39
 
40
  /// Create a symbol string pointer from the given string.
41
  SymbolStringPtr intern(StringRef S);
42
 
43
  /// Remove from the pool any entries that are no longer referenced.
44
  void clearDeadEntries();
45
 
46
  /// Returns true if the pool is empty.
47
  bool empty() const;
48
private:
49
  using RefCountType = std::atomic<size_t>;
50
  using PoolMap = StringMap<RefCountType>;
51
  using PoolMapEntry = StringMapEntry<RefCountType>;
52
  mutable std::mutex PoolMutex;
53
  PoolMap Pool;
54
};
55
 
56
/// Pointer to a pooled string representing a symbol name.
57
class SymbolStringPtr {
58
  friend class OrcV2CAPIHelper;
59
  friend class SymbolStringPool;
60
  friend struct DenseMapInfo<SymbolStringPtr>;
61
 
62
public:
63
  SymbolStringPtr() = default;
64
  SymbolStringPtr(std::nullptr_t) {}
65
  SymbolStringPtr(const SymbolStringPtr &Other)
66
    : S(Other.S) {
67
    if (isRealPoolEntry(S))
68
      ++S->getValue();
69
  }
70
 
71
  SymbolStringPtr& operator=(const SymbolStringPtr &Other) {
72
    if (isRealPoolEntry(S)) {
73
      assert(S->getValue() && "Releasing SymbolStringPtr with zero ref count");
74
      --S->getValue();
75
    }
76
    S = Other.S;
77
    if (isRealPoolEntry(S))
78
      ++S->getValue();
79
    return *this;
80
  }
81
 
82
  SymbolStringPtr(SymbolStringPtr &&Other) : S(nullptr) {
83
    std::swap(S, Other.S);
84
  }
85
 
86
  SymbolStringPtr& operator=(SymbolStringPtr &&Other) {
87
    if (isRealPoolEntry(S)) {
88
      assert(S->getValue() && "Releasing SymbolStringPtr with zero ref count");
89
      --S->getValue();
90
    }
91
    S = nullptr;
92
    std::swap(S, Other.S);
93
    return *this;
94
  }
95
 
96
  ~SymbolStringPtr() {
97
    if (isRealPoolEntry(S)) {
98
      assert(S->getValue() && "Releasing SymbolStringPtr with zero ref count");
99
      --S->getValue();
100
    }
101
  }
102
 
103
  explicit operator bool() const { return S; }
104
 
105
  StringRef operator*() const { return S->first(); }
106
 
107
  friend bool operator==(const SymbolStringPtr &LHS,
108
                         const SymbolStringPtr &RHS) {
109
    return LHS.S == RHS.S;
110
  }
111
 
112
  friend bool operator!=(const SymbolStringPtr &LHS,
113
                         const SymbolStringPtr &RHS) {
114
    return !(LHS == RHS);
115
  }
116
 
117
  friend bool operator<(const SymbolStringPtr &LHS,
118
                        const SymbolStringPtr &RHS) {
119
    return LHS.S < RHS.S;
120
  }
121
 
122
private:
123
  using PoolEntry = SymbolStringPool::PoolMapEntry;
124
  using PoolEntryPtr = PoolEntry *;
125
 
126
  SymbolStringPtr(SymbolStringPool::PoolMapEntry *S)
127
      : S(S) {
128
    if (isRealPoolEntry(S))
129
      ++S->getValue();
130
  }
131
 
132
  // Returns false for null, empty, and tombstone values, true otherwise.
133
  bool isRealPoolEntry(PoolEntryPtr P) {
134
    return ((reinterpret_cast<uintptr_t>(P) - 1) & InvalidPtrMask) !=
135
           InvalidPtrMask;
136
  }
137
 
138
  static SymbolStringPtr getEmptyVal() {
139
    return SymbolStringPtr(reinterpret_cast<PoolEntryPtr>(EmptyBitPattern));
140
  }
141
 
142
  static SymbolStringPtr getTombstoneVal() {
143
    return SymbolStringPtr(reinterpret_cast<PoolEntryPtr>(TombstoneBitPattern));
144
  }
145
 
146
  constexpr static uintptr_t EmptyBitPattern =
147
      std::numeric_limits<uintptr_t>::max()
148
      << PointerLikeTypeTraits<PoolEntryPtr>::NumLowBitsAvailable;
149
 
150
  constexpr static uintptr_t TombstoneBitPattern =
151
      (std::numeric_limits<uintptr_t>::max() - 1)
152
      << PointerLikeTypeTraits<PoolEntryPtr>::NumLowBitsAvailable;
153
 
154
  constexpr static uintptr_t InvalidPtrMask =
155
      (std::numeric_limits<uintptr_t>::max() - 3)
156
      << PointerLikeTypeTraits<PoolEntryPtr>::NumLowBitsAvailable;
157
 
158
  PoolEntryPtr S = nullptr;
159
};
160
 
161
inline SymbolStringPool::~SymbolStringPool() {
162
#ifndef NDEBUG
163
  clearDeadEntries();
164
  assert(Pool.empty() && "Dangling references at pool destruction time");
165
#endif // NDEBUG
166
}
167
 
168
inline SymbolStringPtr SymbolStringPool::intern(StringRef S) {
169
  std::lock_guard<std::mutex> Lock(PoolMutex);
170
  PoolMap::iterator I;
171
  bool Added;
172
  std::tie(I, Added) = Pool.try_emplace(S, 0);
173
  return SymbolStringPtr(&*I);
174
}
175
 
176
inline void SymbolStringPool::clearDeadEntries() {
177
  std::lock_guard<std::mutex> Lock(PoolMutex);
178
  for (auto I = Pool.begin(), E = Pool.end(); I != E;) {
179
    auto Tmp = I++;
180
    if (Tmp->second == 0)
181
      Pool.erase(Tmp);
182
  }
183
}
184
 
185
inline bool SymbolStringPool::empty() const {
186
  std::lock_guard<std::mutex> Lock(PoolMutex);
187
  return Pool.empty();
188
}
189
 
190
} // end namespace orc
191
 
192
template <>
193
struct DenseMapInfo<orc::SymbolStringPtr> {
194
 
195
  static orc::SymbolStringPtr getEmptyKey() {
196
    return orc::SymbolStringPtr::getEmptyVal();
197
  }
198
 
199
  static orc::SymbolStringPtr getTombstoneKey() {
200
    return orc::SymbolStringPtr::getTombstoneVal();
201
  }
202
 
203
  static unsigned getHashValue(const orc::SymbolStringPtr &V) {
204
    return DenseMapInfo<orc::SymbolStringPtr::PoolEntryPtr>::getHashValue(V.S);
205
  }
206
 
207
  static bool isEqual(const orc::SymbolStringPtr &LHS,
208
                      const orc::SymbolStringPtr &RHS) {
209
    return LHS.S == RHS.S;
210
  }
211
};
212
 
213
} // end namespace llvm
214
 
215
#endif // LLVM_EXECUTIONENGINE_ORC_SYMBOLSTRINGPOOL_H