PerThreadBumpPtrAllocator allows separating allocations by thread id. That makes allocations race free. It is possible because ThreadPoolExecutor class creates threads, keeps them until the destructor of ThreadPoolExecutor is called, and assigns ids to the threads. Thus PerThreadBumpPtrAllocator should be used with only threads created by ThreadPoolExecutor. This allocator is useful when thread safe BumpPtrAllocator is needed. Reviewed By: MaskRay, dexonsmith, andrewng Differential Revision: https://reviews.llvm.org/D142318
119 lines
4.0 KiB
C++
119 lines
4.0 KiB
C++
//===- llvm/unittest/DWARFLinkerParallel/StringTableTest.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/DWARFLinkerParallel/StringTable.h"
|
|
#include "llvm/Support/Parallel.h"
|
|
#include "gtest/gtest.h"
|
|
#include <cstdlib>
|
|
|
|
using namespace llvm;
|
|
using namespace dwarflinker_parallel;
|
|
|
|
namespace {
|
|
|
|
TEST(StringPoolTest, TestStringTable) {
|
|
struct StringDescription {
|
|
const char *Str = nullptr;
|
|
uint64_t Idx = 0;
|
|
uint64_t Offset = 0;
|
|
};
|
|
|
|
SmallVector<StringDescription> InputStrings = {
|
|
{"first", 0, 0}, {"second", 1, 6}, {"third", 2, 13}};
|
|
|
|
StringPool Strings;
|
|
StringTable OutStrings(Strings, nullptr);
|
|
|
|
// StringPool uses PerThreadBumpPtrAllocator which should be accessed from
|
|
// threads created by ThreadPoolExecutor. Use TaskGroup to run on
|
|
// ThreadPoolExecutor threads.
|
|
parallel::TaskGroup tg;
|
|
|
|
tg.spawn([&]() {
|
|
// Check string insertion.
|
|
StringEntry *FirstPtr = Strings.insert(InputStrings[0].Str).first;
|
|
StringEntry *SecondPtr = Strings.insert(InputStrings[1].Str).first;
|
|
StringEntry *ThirdPtr = Strings.insert(InputStrings[2].Str).first;
|
|
|
|
FirstPtr = OutStrings.add(FirstPtr);
|
|
SecondPtr = OutStrings.add(SecondPtr);
|
|
ThirdPtr = OutStrings.add(ThirdPtr);
|
|
|
|
// Check fields of inserted strings.
|
|
EXPECT_TRUE(FirstPtr->getKey() == InputStrings[0].Str);
|
|
EXPECT_TRUE(FirstPtr->getValue()->Offset == InputStrings[0].Offset);
|
|
EXPECT_TRUE(FirstPtr->getValue()->Index == InputStrings[0].Idx);
|
|
|
|
EXPECT_TRUE(SecondPtr->getKey() == InputStrings[1].Str);
|
|
EXPECT_TRUE(SecondPtr->getValue()->Offset == InputStrings[1].Offset);
|
|
EXPECT_TRUE(SecondPtr->getValue()->Index == InputStrings[1].Idx);
|
|
|
|
EXPECT_TRUE(ThirdPtr->getKey() == InputStrings[2].Str);
|
|
EXPECT_TRUE(ThirdPtr->getValue()->Offset == InputStrings[2].Offset);
|
|
EXPECT_TRUE(ThirdPtr->getValue()->Index == InputStrings[2].Idx);
|
|
|
|
// Check order enumerated strings.
|
|
uint64_t CurIdx = 0;
|
|
std::function<void(DwarfStringPoolEntryRef)> checkStr =
|
|
[&](DwarfStringPoolEntryRef Entry) {
|
|
EXPECT_TRUE(Entry.getEntry().isIndexed());
|
|
EXPECT_TRUE(Entry.getIndex() == CurIdx);
|
|
EXPECT_TRUE(Entry.getOffset() == InputStrings[CurIdx].Offset);
|
|
EXPECT_TRUE(Entry.getString() == InputStrings[CurIdx].Str);
|
|
|
|
CurIdx++;
|
|
};
|
|
|
|
OutStrings.forEach(checkStr);
|
|
});
|
|
}
|
|
|
|
TEST(StringPoolTest, TestStringTableWithTranslator) {
|
|
std::string Word;
|
|
std::function<StringRef(StringRef)> TranslatorFunc =
|
|
[&](StringRef InputString) -> StringRef {
|
|
Word.clear();
|
|
for (auto Sym : InputString)
|
|
Word.insert(Word.begin(), Sym);
|
|
Word += '0';
|
|
return Word;
|
|
};
|
|
|
|
StringPool Strings;
|
|
StringTable OutStrings(Strings, TranslatorFunc);
|
|
|
|
// StringPool uses PerThreadBumpPtrAllocator which should be accessed from
|
|
// threads created by ThreadPoolExecutor. Use TaskGroup to run on
|
|
// ThreadPoolExecutor threads.
|
|
parallel::TaskGroup tg;
|
|
|
|
tg.spawn([&]() {
|
|
StringEntry *FirstPtr = Strings.insert("first").first;
|
|
StringEntry *SecondPtr = Strings.insert("second").first;
|
|
StringEntry *ThirdPtr = Strings.insert("third").first;
|
|
|
|
FirstPtr = OutStrings.add(FirstPtr);
|
|
SecondPtr = OutStrings.add(SecondPtr);
|
|
ThirdPtr = OutStrings.add(ThirdPtr);
|
|
|
|
EXPECT_TRUE(FirstPtr->getKey() == "tsrif0");
|
|
EXPECT_TRUE(FirstPtr->getValue()->Offset == 0);
|
|
EXPECT_TRUE(FirstPtr->getValue()->Index == 0);
|
|
|
|
EXPECT_TRUE(SecondPtr->getKey() == "dnoces0");
|
|
EXPECT_TRUE(SecondPtr->getValue()->Offset == 7);
|
|
EXPECT_TRUE(SecondPtr->getValue()->Index == 1);
|
|
|
|
EXPECT_TRUE(ThirdPtr->getKey() == "driht0");
|
|
EXPECT_TRUE(ThirdPtr->getValue()->Offset == 15);
|
|
EXPECT_TRUE(ThirdPtr->getValue()->Index == 2);
|
|
});
|
|
}
|
|
|
|
} // anonymous namespace
|