mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-01-11 10:26:44 +00:00
[XRay] Handle allocator exhaustion in segmented array
Summary: This change allows us to handle allocator exhaustion properly in the segmented array implementation. Before this change, we relied on the caller of the `trim` function to provide a valid number of elements to trim. This change allows us to do the right thing in case the elements to trim is greater than the size of the container. Reviewers: mboerger, eizan Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D53484 llvm-svn: 344880
This commit is contained in:
parent
dbabdfaca5
commit
ebfbf89000
@ -1,9 +1,13 @@
|
||||
#include "test_helpers.h"
|
||||
#include "xray_segmented_array.h"
|
||||
#include "gmock/gmock.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
namespace __xray {
|
||||
namespace {
|
||||
|
||||
using ::testing::SizeIs;
|
||||
|
||||
struct TestData {
|
||||
s64 First;
|
||||
s64 Second;
|
||||
@ -12,6 +16,10 @@ struct TestData {
|
||||
TestData(s64 F, s64 S) : First(F), Second(S) {}
|
||||
};
|
||||
|
||||
void PrintTo(const TestData &D, std::ostream *OS) {
|
||||
*OS << "{ " << D.First << ", " << D.Second << " }";
|
||||
}
|
||||
|
||||
TEST(SegmentedArrayTest, ConstructWithAllocators) {
|
||||
using AllocatorType = typename Array<TestData>::AllocatorType;
|
||||
AllocatorType A(1 << 4);
|
||||
@ -161,6 +169,23 @@ TEST(SegmentedArrayTest, IteratorTrimBehaviour) {
|
||||
EXPECT_EQ(Data.size(), SegmentX2);
|
||||
}
|
||||
|
||||
TEST(SegmentedArrayTest, HandleExhaustedAllocator) {
|
||||
using AllocatorType = typename Array<TestData>::AllocatorType;
|
||||
constexpr auto Segment = Array<TestData>::SegmentSize;
|
||||
constexpr auto MaxElements = Array<TestData>::ElementsPerSegment;
|
||||
AllocatorType A(Segment);
|
||||
Array<TestData> Data(A);
|
||||
for (auto i = MaxElements; i > 0u; --i)
|
||||
EXPECT_NE(Data.AppendEmplace(static_cast<s64>(i), static_cast<s64>(i)),
|
||||
nullptr);
|
||||
EXPECT_EQ(Data.AppendEmplace(0, 0), nullptr);
|
||||
EXPECT_THAT(Data, SizeIs(MaxElements));
|
||||
|
||||
// Trimming more elements than there are in the container should be fine.
|
||||
Data.trim(MaxElements + 1);
|
||||
EXPECT_THAT(Data, SizeIs(0u));
|
||||
}
|
||||
|
||||
struct ShadowStackEntry {
|
||||
uint64_t EntryTSC = 0;
|
||||
uint64_t *NodePtr = nullptr;
|
||||
|
@ -14,8 +14,9 @@
|
||||
#define COMPILER_RT_LIB_XRAY_TESTS_TEST_HELPERS_H_
|
||||
|
||||
#include "xray_buffer_queue.h"
|
||||
#include "llvm/XRay/XRayRecord.h"
|
||||
#include "xray_segmented_array.h"
|
||||
#include "llvm/XRay/Trace.h"
|
||||
#include "llvm/XRay/XRayRecord.h"
|
||||
#include "gmock/gmock.h"
|
||||
|
||||
// TODO: Move these to llvm/include/Testing/XRay/...
|
||||
@ -54,6 +55,19 @@ namespace __xray {
|
||||
|
||||
std::string serialize(BufferQueue &Buffers, int32_t Version);
|
||||
|
||||
template <class T> void PrintTo(const Array<T> &A, std::ostream *OS) {
|
||||
*OS << "[";
|
||||
bool first = true;
|
||||
for (const auto &E : A) {
|
||||
if (!first) {
|
||||
*OS << ", ";
|
||||
}
|
||||
PrintTo(E, OS);
|
||||
first = false;
|
||||
}
|
||||
*OS << "]";
|
||||
}
|
||||
|
||||
} // namespace __xray
|
||||
|
||||
#endif // COMPILER_RT_LIB_XRAY_TESTS_TEST_HELPERS_H_
|
||||
|
@ -78,6 +78,8 @@ public:
|
||||
|
||||
static SegmentBase SentinelSegment;
|
||||
|
||||
using size_type = size_t;
|
||||
|
||||
private:
|
||||
AllocatorType *Alloc;
|
||||
SegmentBase *Head = &SentinelSegment;
|
||||
@ -334,9 +336,8 @@ public:
|
||||
if (Elements == 0)
|
||||
return;
|
||||
|
||||
DCHECK_LE(Elements, Size);
|
||||
DCHECK_GT(Size, 0);
|
||||
auto OldSize = Size;
|
||||
Elements = Elements >= Size ? Size : Elements;
|
||||
Size -= Elements;
|
||||
|
||||
DCHECK_NE(Head, &SentinelSegment);
|
||||
@ -346,8 +347,11 @@ public:
|
||||
nearest_boundary(Size, ElementsPerSegment)) /
|
||||
ElementsPerSegment;
|
||||
SegmentsToTrim > 0; --SegmentsToTrim) {
|
||||
DCHECK_NE(Head, &SentinelSegment);
|
||||
DCHECK_NE(Tail, &SentinelSegment);
|
||||
|
||||
// We want to short-circuit if the trace is already empty.
|
||||
if (Head == &SentinelSegment && Head == Tail)
|
||||
return;
|
||||
|
||||
// Put the tail into the Freelist.
|
||||
auto *FreeSegment = Tail;
|
||||
Tail = Tail->Prev;
|
||||
|
Loading…
x
Reference in New Issue
Block a user