diff --git a/llvm/include/llvm/DWARFLinkerNext/StringPool.h b/llvm/include/llvm/DWARFLinkerNext/StringPool.h new file mode 100644 --- /dev/null +++ b/llvm/include/llvm/DWARFLinkerNext/StringPool.h @@ -0,0 +1,71 @@ +//===- StringPool.h ---------------------------------------------*- 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 +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DWARFLINKERNEXT_STRINGPOOL_H +#define LLVM_DWARFLINKERNEXT_STRINGPOOL_H + +#include "llvm/ADT/ConcurrentHashtable.h" +#include "llvm/CodeGen/DwarfStringPoolEntry.h" +#include "llvm/Support/Allocator.h" +#include +#include + +namespace llvm { +namespace dwarflinker { + +/// StringEntry keeps data of the string: the length, external offset +/// and a string body which is placed right after StringEntry. +using StringEntry = StringMapEntry; + +class StringPoolEntryInfo { +public: + /// \returns Hash value for the specified \p Key. + static inline hash_code getHashValue(const StringRef &Key) { + return std::hash{}( + std::string_view(Key.data(), Key.size())); + } + + /// \returns true if both \p LHS and \p RHS are equal. + static inline bool isEqual(const StringRef &LHS, const StringRef &RHS) { + return LHS == RHS; + } + + /// \returns key for the specified \p KeyData. + static inline StringRef getKey(const StringEntry &KeyData) { + return KeyData.getKey(); + } + + /// \returns newly created object of KeyDataTy type. + static inline StringEntry *create(const StringRef &Key, + BumpPtrAllocator &Allocator) { + return StringEntry::create(Key, Allocator); + } +}; + +class StringPool + : public ConcurrentHashTableByPtr { +public: + StringPool() + : ConcurrentHashTableByPtr() {} + StringPool(size_t InitialSize) + : ConcurrentHashTableByPtr( + InitialSize) {} + + static inline BumpPtrAllocator &getAllocatorRef() { return Allocator; } + +private: + static thread_local BumpPtrAllocator Allocator; +}; + +} // end of namespace dwarflinker +} // end namespace llvm + +#endif // LLVM_DWARFLINKERNEXT_STRINGPOOL_H diff --git a/llvm/lib/DWARFLinkerNext/CMakeLists.txt b/llvm/lib/DWARFLinkerNext/CMakeLists.txt --- a/llvm/lib/DWARFLinkerNext/CMakeLists.txt +++ b/llvm/lib/DWARFLinkerNext/CMakeLists.txt @@ -1,5 +1,6 @@ add_llvm_component_library(LLVMDWARFLinkerNext DWARFLinker.cpp + StringPool.cpp ADDITIONAL_HEADER_DIRS ${LLVM_MAIN_INCLUDE_DIR}/llvm/DWARFLinkerNext diff --git a/llvm/lib/DWARFLinkerNext/StringPool.cpp b/llvm/lib/DWARFLinkerNext/StringPool.cpp new file mode 100644 --- /dev/null +++ b/llvm/lib/DWARFLinkerNext/StringPool.cpp @@ -0,0 +1,13 @@ +//=== StringPool.cpp ------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "llvm/DWARFLinkerNext/StringPool.h" + +using namespace llvm; + +thread_local BumpPtrAllocator dwarflinker::StringPool::Allocator; diff --git a/llvm/unittests/DWARFLinkerNext/CMakeLists.txt b/llvm/unittests/DWARFLinkerNext/CMakeLists.txt --- a/llvm/unittests/DWARFLinkerNext/CMakeLists.txt +++ b/llvm/unittests/DWARFLinkerNext/CMakeLists.txt @@ -1,9 +1,11 @@ set(LLVM_LINK_COMPONENTS Support + DWARFLinkerNext ) add_llvm_unittest(DWARFLinkerNextTests ListTest.cpp + StringPoolTest.cpp ) target_link_libraries(DWARFLinkerNextTests PRIVATE LLVMTestingSupport) diff --git a/llvm/unittests/DWARFLinkerNext/StringPoolTest.cpp b/llvm/unittests/DWARFLinkerNext/StringPoolTest.cpp new file mode 100644 --- /dev/null +++ b/llvm/unittests/DWARFLinkerNext/StringPoolTest.cpp @@ -0,0 +1,62 @@ +//===- llvm/unittest/DWARFLinkerNext/StringPoolTest.cpp -------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "llvm/DWARFLinkerNext/StringPool.h" +#include "llvm/Support/Parallel.h" +#include "gtest/gtest.h" +#include + +using namespace llvm; +using namespace dwarflinker; + +namespace { + +TEST(StringPoolTest, TestStringPool) { + StringPool Strings; + + std::pair Entry = Strings.insert("test"); + EXPECT_TRUE(Entry.second); + EXPECT_TRUE(Entry.first->getKey() == "test"); + EXPECT_TRUE(Entry.first->second == nullptr); + + StringEntry *EntryPtr = Entry.first; + + Entry = Strings.insert("test"); + EXPECT_FALSE(Entry.second); + EXPECT_TRUE(Entry.first->getKey() == "test"); + EXPECT_TRUE(Entry.first->second == nullptr); + EXPECT_TRUE(EntryPtr == Entry.first); + + Entry = Strings.insert("test2"); + EXPECT_TRUE(Entry.second); + EXPECT_TRUE(Entry.first->getKey() == "test2"); + EXPECT_TRUE(Entry.first->second == nullptr); + EXPECT_TRUE(EntryPtr != Entry.first); +} + +TEST(StringPoolTest, TestStringPoolParallel) { + StringPool Strings; + + // Add data. + parallelFor(0, 1000, [&](size_t Idx) { + std::pair Entry = Strings.insert(std::to_string(Idx)); + EXPECT_TRUE(Entry.second); + EXPECT_TRUE(Entry.first->getKey() == std::to_string(Idx)); + EXPECT_TRUE(Entry.first->second == nullptr); + }); + + // Check data. + parallelFor(0, 1000, [&](size_t Idx) { + std::pair Entry = Strings.insert(std::to_string(Idx)); + EXPECT_FALSE(Entry.second); + EXPECT_TRUE(Entry.first->getKey() == std::to_string(Idx)); + EXPECT_TRUE(Entry.first->second == nullptr); + }); +} + +} // anonymous namespace