Files
archived-llvm/include/llvm/ExecutionEngine/Orc/SymbolStringPool.h
Chandler Carruth 6b547686c5 Update the file headers across all of the LLVM projects in the monorepo
to reflect the new license.

We understand that people may be surprised that we're moving the header
entirely to discuss the new license. We checked this carefully with the
Foundation's lawyer and we believe this is the correct approach.

Essentially, all code in the project is now made available by the LLVM
project under our new license, so you will see that the license headers
include that license only. Some of our contributors have contributed
code under our old license, and accordingly, we have retained a copy of
our old license notice in the top-level files in each project and
repository.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@351636 91177308-0d34-0410-b5e6-96231b3b80d8
2019-01-19 08:50:56 +00:00

174 lines
4.3 KiB
C++

//===- SymbolStringPool.h - Multi-threaded pool for JIT symbols -*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// 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/DenseMap.h"
#include "llvm/ADT/StringMap.h"
#include <atomic>
#include <mutex>
namespace llvm {
namespace orc {
class SymbolStringPtr;
/// String pool for symbol names used by the JIT.
class SymbolStringPool {
friend class SymbolStringPtr;
public:
/// Destroy a SymbolStringPool.
~SymbolStringPool();
/// Create a symbol string pointer from the given string.
SymbolStringPtr intern(StringRef S);
/// Remove from the pool any entries that are no longer referenced.
void clearDeadEntries();
/// Returns true if the pool is empty.
bool empty() const;
private:
using RefCountType = std::atomic<size_t>;
using PoolMap = StringMap<RefCountType>;
using PoolMapEntry = StringMapEntry<RefCountType>;
mutable std::mutex PoolMutex;
PoolMap Pool;
};
/// Pointer to a pooled string representing a symbol name.
class SymbolStringPtr {
friend class SymbolStringPool;
friend struct DenseMapInfo<SymbolStringPtr>;
friend bool operator==(const SymbolStringPtr &LHS,
const SymbolStringPtr &RHS);
friend bool operator<(const SymbolStringPtr &LHS, const SymbolStringPtr &RHS);
static SymbolStringPool::PoolMapEntry Tombstone;
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();
}
StringRef operator*() const { return S->first(); }
private:
SymbolStringPtr(SymbolStringPool::PoolMapEntry *S)
: S(S) {
if (S)
++S->getValue();
}
SymbolStringPool::PoolMapEntry *S = nullptr;
};
inline bool operator==(const SymbolStringPtr &LHS, const SymbolStringPtr &RHS) {
return LHS.S == RHS.S;
}
inline bool operator!=(const SymbolStringPtr &LHS, const SymbolStringPtr &RHS) {
return !(LHS == RHS);
}
inline bool operator<(const SymbolStringPtr &LHS, const SymbolStringPtr &RHS) {
return LHS.S < RHS.S;
}
inline SymbolStringPool::~SymbolStringPool() {
#ifndef NDEBUG
clearDeadEntries();
assert(Pool.empty() && "Dangling references at pool destruction time");
#endif // NDEBUG
}
inline SymbolStringPtr SymbolStringPool::intern(StringRef S) {
std::lock_guard<std::mutex> Lock(PoolMutex);
PoolMap::iterator I;
bool Added;
std::tie(I, Added) = Pool.try_emplace(S, 0);
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 = I++;
if (Tmp->second == 0)
Pool.erase(Tmp);
}
}
inline bool SymbolStringPool::empty() const {
std::lock_guard<std::mutex> Lock(PoolMutex);
return Pool.empty();
}
} // end namespace orc
template <>
struct DenseMapInfo<orc::SymbolStringPtr> {
static orc::SymbolStringPtr getEmptyKey() {
return orc::SymbolStringPtr();
}
static orc::SymbolStringPtr getTombstoneKey() {
return orc::SymbolStringPtr(&orc::SymbolStringPtr::Tombstone);
}
static unsigned getHashValue(orc::SymbolStringPtr V) {
uintptr_t IV = reinterpret_cast<uintptr_t>(V.S);
return unsigned(IV) ^ unsigned(IV >> 9);
}
static bool isEqual(const orc::SymbolStringPtr &LHS,
const orc::SymbolStringPtr &RHS) {
return LHS.S == RHS.S;
}
};
} // end namespace llvm
#endif // LLVM_EXECUTIONENGINE_ORC_SYMBOLSTRINGPOOL_H