[llvm] r319839 - [Orc] Add a SymbolStringPool data structure for efficient storage and fast
David Blaikie via llvm-commits
llvm-commits at lists.llvm.org
Thu Dec 14 13:21:02 PST 2017
On Tue, Dec 5, 2017 at 1:45 PM Lang Hames via llvm-commits <
llvm-commits at lists.llvm.org> wrote:
> 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 {
>
In general, any op overload that can be a non-member should be (though it
can still be a friend and defined inline, so it doesn't change the code
much) so that any conversions that apply to the RHS apply equally to the
LHS.
> + 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);
>
This implementation involves two map lookups (one to find, another to
emplace if the find fails) - if you call try_emplace first, and inspect its
"Added" result to decide what to do (you might not have to do anything,
actually), then you can use one lookup.
> + 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;
>
This ^ might be better written as:
auto Tmp = I++;
if (Tmp->second == 0)
Pool.erase(Tmp);
So there's no need to "remember" the assignment to I at the end? (action at
a distance, etc) - though I can appreciate having the "increment" action at
the end of the loop as it's written here.
> + }
> +}
> +
> +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";
> +}
> +
> +}
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20171214/ca670f0c/attachment.html>
More information about the llvm-commits
mailing list