[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