[llvm] r319839 - [Orc] Add a SymbolStringPool data structure for efficient storage and fast
Lang Hames via llvm-commits
llvm-commits at lists.llvm.org
Tue Dec 5 13:44:56 PST 2017
Author: lhames
Date: Tue Dec 5 13:44:56 2017
New Revision: 319839
URL: http://llvm.org/viewvc/llvm-project?rev=319839&view=rev
Log:
[Orc] Add a SymbolStringPool data structure for efficient storage and fast
comparison of symbol names.
SymbolStringPool is a thread-safe string pool that will be used in upcoming Orc
APIs to facilitate efficient storage and fast comparison of symbol name strings.
Added:
llvm/trunk/include/llvm/ExecutionEngine/Orc/SymbolStringPool.h
llvm/trunk/unittests/ExecutionEngine/Orc/SymbolStringPoolTest.cpp
Modified:
llvm/trunk/unittests/ExecutionEngine/Orc/CMakeLists.txt
Added: llvm/trunk/include/llvm/ExecutionEngine/Orc/SymbolStringPool.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ExecutionEngine/Orc/SymbolStringPool.h?rev=319839&view=auto
==============================================================================
--- llvm/trunk/include/llvm/ExecutionEngine/Orc/SymbolStringPool.h (added)
+++ llvm/trunk/include/llvm/ExecutionEngine/Orc/SymbolStringPool.h Tue Dec 5 13:44:56 2017
@@ -0,0 +1,133 @@
+//===- SymbolStringPool.h - Multi-threaded pool for JIT symbols -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// 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/StringMap.h"
+#include <atomic>
+#include <mutex>
+
+namespace llvm {
+namespace orc {
+
+class SymbolStringPtr;
+
+/// @brief String pool for symbol names used by the JIT.
+class SymbolStringPool {
+ friend class SymbolStringPtr;
+public:
+ /// @brief Create a symbol string pointer from the given string.
+ SymbolStringPtr intern(StringRef S);
+
+ /// @brief Remove from the pool any entries that are no longer referenced.
+ void clearDeadEntries();
+
+ /// @brief Returns true if the pool is empty.
+ bool empty() const;
+private:
+ using RefCountType = std::atomic_uint64_t;
+ using PoolMap = StringMap<RefCountType>;
+ using PoolMapEntry = StringMapEntry<RefCountType>;
+ mutable std::mutex PoolMutex;
+ PoolMap Pool;
+};
+
+/// @brief Pointer to a pooled string representing a symbol name.
+class SymbolStringPtr {
+ friend class SymbolStringPool;
+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();
+ }
+
+ bool operator==(const SymbolStringPtr &Other) const {
+ return S == Other.S;
+ }
+
+ bool operator!=(const SymbolStringPtr &Other) const {
+ return !(*this == Other);
+ }
+
+private:
+
+ SymbolStringPtr(SymbolStringPool::PoolMapEntry *S)
+ : S(S) {
+ if (S)
+ ++S->getValue();
+ }
+
+ SymbolStringPool::PoolMapEntry *S = nullptr;
+};
+
+SymbolStringPtr SymbolStringPool::intern(StringRef S) {
+ std::lock_guard<std::mutex> Lock(PoolMutex);
+ auto I = Pool.find(S);
+ if (I != Pool.end())
+ return SymbolStringPtr(&*I);
+
+ bool Added;
+ std::tie(I, Added) = Pool.try_emplace(S, 0);
+ assert(Added && "Insert should always succeed here");
+ return SymbolStringPtr(&*I);
+}
+
+void SymbolStringPool::clearDeadEntries() {
+ std::lock_guard<std::mutex> Lock(PoolMutex);
+ for (auto I = Pool.begin(), E = Pool.end(); I != E;) {
+ auto Tmp = std::next(I);
+ if (I->second == 0)
+ Pool.erase(I);
+ I = Tmp;
+ }
+}
+
+bool SymbolStringPool::empty() const {
+ std::lock_guard<std::mutex> Lock(PoolMutex);
+ return Pool.empty();
+}
+
+} // end namespace orc
+
+} // end namespace llvm
+
+#endif // LLVM_EXECUTIONENGINE_ORC_SYMBOLSTRINGPOOL_H
Modified: llvm/trunk/unittests/ExecutionEngine/Orc/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/ExecutionEngine/Orc/CMakeLists.txt?rev=319839&r1=319838&r2=319839&view=diff
==============================================================================
--- llvm/trunk/unittests/ExecutionEngine/Orc/CMakeLists.txt (original)
+++ llvm/trunk/unittests/ExecutionEngine/Orc/CMakeLists.txt Tue Dec 5 13:44:56 2017
@@ -21,6 +21,7 @@ add_llvm_unittest(OrcJITTests
RemoteObjectLayerTest.cpp
RPCUtilsTest.cpp
RTDyldObjectLinkingLayerTest.cpp
+ SymbolStringPoolTest.cpp
)
target_link_libraries(OrcJITTests ${LLVM_PTHREAD_LIB})
Added: llvm/trunk/unittests/ExecutionEngine/Orc/SymbolStringPoolTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/ExecutionEngine/Orc/SymbolStringPoolTest.cpp?rev=319839&view=auto
==============================================================================
--- llvm/trunk/unittests/ExecutionEngine/Orc/SymbolStringPoolTest.cpp (added)
+++ llvm/trunk/unittests/ExecutionEngine/Orc/SymbolStringPoolTest.cpp Tue Dec 5 13:44:56 2017
@@ -0,0 +1,43 @@
+//===----- SymbolStringPoolTest.cpp - Unit tests for SymbolStringPool -----===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ExecutionEngine/Orc/SymbolStringPool.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+using namespace llvm::orc;
+
+namespace {
+
+TEST(SymbolStringPool, UniquingAndEquality) {
+ SymbolStringPool SP;
+ auto P1 = SP.intern("hello");
+
+ std::string S("hel");
+ S += "lo";
+ auto P2 = SP.intern(S);
+
+ auto P3 = SP.intern("goodbye");
+
+ EXPECT_EQ(P1, P2) << "Failed to unique entries";
+ EXPECT_NE(P1, P3) << "Inequal pooled symbol strings comparing equal";
+}
+
+TEST(SymbolStringPool, ClearDeadEntries) {
+ SymbolStringPool SP;
+ {
+ auto P1 = SP.intern("s1");
+ SP.clearDeadEntries();
+ EXPECT_FALSE(SP.empty()) << "\"s1\" entry in pool should still be retained";
+ }
+ SP.clearDeadEntries();
+ EXPECT_TRUE(SP.empty()) << "pool should be empty";
+}
+
+}
More information about the llvm-commits
mailing list