From 8a0631a35e7719c5a3dc8678ec342fe5a83170da Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Sat, 5 Jan 2013 00:57:11 +0000 Subject: Add an ArrayRecycler class. This is similar to the existing Recycler allocator, but instead of recycling individual objects from a BumpPtrAllocator, arrays of different sizes can be allocated. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@171581 91177308-0d34-0410-b5e6-96231b3b80d8 --- unittests/Support/ArrayRecylerTest.cpp | 109 +++++++++++++++++++++++++++++++++ unittests/Support/CMakeLists.txt | 1 + 2 files changed, 110 insertions(+) create mode 100644 unittests/Support/ArrayRecylerTest.cpp (limited to 'unittests') diff --git a/unittests/Support/ArrayRecylerTest.cpp b/unittests/Support/ArrayRecylerTest.cpp new file mode 100644 index 0000000..1ff97ba --- /dev/null +++ b/unittests/Support/ArrayRecylerTest.cpp @@ -0,0 +1,109 @@ +//===--- unittest/Support/ArrayRecyclerTest.cpp ---------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/ArrayRecycler.h" +#include "llvm/Support/Allocator.h" +#include "gtest/gtest.h" +#include + +using namespace llvm; + +namespace { + +struct Object { + int Num; + Object *Other; +}; +typedef ArrayRecycler ARO; + +TEST(ArrayRecyclerTest, Capacity) { + // Capacity size should never be 0. + ARO::Capacity Cap = ARO::Capacity::get(0); + EXPECT_LT(0u, Cap.getSize()); + + size_t PrevSize = Cap.getSize(); + for (unsigned N = 1; N != 100; ++N) { + Cap = ARO::Capacity::get(N); + EXPECT_LE(N, Cap.getSize()); + if (PrevSize >= N) + EXPECT_EQ(PrevSize, Cap.getSize()); + else + EXPECT_LT(PrevSize, Cap.getSize()); + PrevSize = Cap.getSize(); + } + + // Check that the buckets are monotonically increasing. + Cap = ARO::Capacity::get(0); + PrevSize = Cap.getSize(); + for (unsigned N = 0; N != 20; ++N) { + Cap = Cap.getNext(); + EXPECT_LT(PrevSize, Cap.getSize()); + PrevSize = Cap.getSize(); + } +} + +TEST(ArrayRecyclerTest, Basics) { + BumpPtrAllocator Allocator; + ArrayRecycler DUT; + + ARO::Capacity Cap = ARO::Capacity::get(8); + Object *A1 = DUT.allocate(Cap, Allocator); + A1[0].Num = 21; + A1[7].Num = 17; + + Object *A2 = DUT.allocate(Cap, Allocator); + A2[0].Num = 121; + A2[7].Num = 117; + + Object *A3 = DUT.allocate(Cap, Allocator); + A3[0].Num = 221; + A3[7].Num = 217; + + EXPECT_EQ(21, A1[0].Num); + EXPECT_EQ(17, A1[7].Num); + EXPECT_EQ(121, A2[0].Num); + EXPECT_EQ(117, A2[7].Num); + EXPECT_EQ(221, A3[0].Num); + EXPECT_EQ(217, A3[7].Num); + + DUT.deallocate(Cap, A2); + + // Check that deallocation didn't clobber anything. + EXPECT_EQ(21, A1[0].Num); + EXPECT_EQ(17, A1[7].Num); + EXPECT_EQ(221, A3[0].Num); + EXPECT_EQ(217, A3[7].Num); + + // Verify recycling. + Object *A2x = DUT.allocate(Cap, Allocator); + EXPECT_EQ(A2, A2x); + + DUT.deallocate(Cap, A2x); + DUT.deallocate(Cap, A1); + DUT.deallocate(Cap, A3); + + // Objects are not required to be recycled in reverse deallocation order, but + // that is what the current implementation does. + Object *A3x = DUT.allocate(Cap, Allocator); + EXPECT_EQ(A3, A3x); + Object *A1x = DUT.allocate(Cap, Allocator); + EXPECT_EQ(A1, A1x); + Object *A2y = DUT.allocate(Cap, Allocator); + EXPECT_EQ(A2, A2y); + + // Back to allocation from the BumpPtrAllocator. + Object *A4 = DUT.allocate(Cap, Allocator); + EXPECT_NE(A1, A4); + EXPECT_NE(A2, A4); + EXPECT_NE(A3, A4); + + DUT.clear(Allocator); +} + +} // end anonymous namespace diff --git a/unittests/Support/CMakeLists.txt b/unittests/Support/CMakeLists.txt index c9a330d..dd42585 100644 --- a/unittests/Support/CMakeLists.txt +++ b/unittests/Support/CMakeLists.txt @@ -6,6 +6,7 @@ set(LLVM_LINK_COMPONENTS add_llvm_unittest(SupportTests AlignOfTest.cpp AllocatorTest.cpp + ArrayRecyclerTest.cpp BlockFrequencyTest.cpp Casting.cpp CommandLineTest.cpp -- cgit v1.1