Upload Kmake

This commit is contained in:
Gorochu
2026-05-26 23:36:42 -07:00
parent ba051b2f74
commit 555ec72358
41615 changed files with 13344630 additions and 1 deletions

View File

@ -0,0 +1,125 @@
// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/zone/zone-allocator.h"
#include <list>
#include <vector>
#include "test/unittests/test-utils.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace v8 {
namespace internal {
template <template <typename T> typename Allocator>
void TestWithStdContainers() {
AccountingAllocator accounting_allocator;
Zone zone(&accounting_allocator, ZONE_NAME);
Allocator<int> zone_allocator(&zone);
// Vector does not require allocator rebinding, list and set do.
{
std::vector<int, Allocator<int>> v(10, zone_allocator);
for (int i = 1; i <= 100; ++i) v.push_back(i);
int sum_of_v = 0;
for (int i : v) sum_of_v += i;
CHECK_EQ(5050, sum_of_v);
}
{
std::list<int, Allocator<int>> l(zone_allocator);
for (int i = 1; i <= 100; ++i) l.push_back(i);
int sum_of_l = 0;
for (int i : l) sum_of_l += i;
CHECK_EQ(5050, sum_of_l);
}
{
std::set<int, std::less<int>, Allocator<int>> s(zone_allocator);
for (int i = 1; i <= 100; ++i) s.insert(i);
int sum_of_s = 0;
for (int i : s) sum_of_s += i;
CHECK_EQ(5050, sum_of_s);
}
}
using ZoneAllocatorTest = TestWithPlatform;
TEST_F(ZoneAllocatorTest, UseWithStdContainers) {
TestWithStdContainers<ZoneAllocator>();
}
using RecyclingZoneAllocatorTest = TestWithPlatform;
TEST_F(RecyclingZoneAllocatorTest, ReuseSameSize) {
AccountingAllocator accounting_allocator;
Zone zone(&accounting_allocator, ZONE_NAME);
RecyclingZoneAllocator<int> zone_allocator(&zone);
int* allocated = zone_allocator.allocate(10);
zone_allocator.deallocate(allocated, 10);
CHECK_EQ(zone_allocator.allocate(10), allocated);
}
TEST_F(RecyclingZoneAllocatorTest, ReuseSmallerSize) {
AccountingAllocator accounting_allocator;
Zone zone(&accounting_allocator, ZONE_NAME);
RecyclingZoneAllocator<int> zone_allocator(&zone);
int* allocated = zone_allocator.allocate(100);
zone_allocator.deallocate(allocated, 100);
CHECK_EQ(zone_allocator.allocate(10), allocated);
}
TEST_F(RecyclingZoneAllocatorTest, DontReuseTooSmallSize) {
AccountingAllocator accounting_allocator;
Zone zone(&accounting_allocator, ZONE_NAME);
RecyclingZoneAllocator<int> zone_allocator(&zone);
// The sizeof(FreeBlock) will be larger than a single int, so we can't keep
// store the free list in the deallocated block.
int* allocated = zone_allocator.allocate(1);
zone_allocator.deallocate(allocated, 1);
CHECK_NE(zone_allocator.allocate(1), allocated);
}
TEST_F(RecyclingZoneAllocatorTest, ReuseMultipleSize) {
AccountingAllocator accounting_allocator;
Zone zone(&accounting_allocator, ZONE_NAME);
RecyclingZoneAllocator<int> zone_allocator(&zone);
int* allocated1 = zone_allocator.allocate(10);
int* allocated2 = zone_allocator.allocate(20);
int* allocated3 = zone_allocator.allocate(30);
zone_allocator.deallocate(allocated1, 10);
zone_allocator.deallocate(allocated2, 20);
zone_allocator.deallocate(allocated3, 30);
CHECK_EQ(zone_allocator.allocate(10), allocated3);
CHECK_EQ(zone_allocator.allocate(10), allocated2);
CHECK_EQ(zone_allocator.allocate(10), allocated1);
}
TEST_F(RecyclingZoneAllocatorTest, DontChainSmallerSizes) {
AccountingAllocator accounting_allocator;
Zone zone(&accounting_allocator, ZONE_NAME);
RecyclingZoneAllocator<int> zone_allocator(&zone);
int* allocated1 = zone_allocator.allocate(10);
int* allocated2 = zone_allocator.allocate(5);
int* allocated3 = zone_allocator.allocate(10);
zone_allocator.deallocate(allocated1, 10);
zone_allocator.deallocate(allocated2, 5);
zone_allocator.deallocate(allocated3, 10);
CHECK_EQ(zone_allocator.allocate(5), allocated3);
CHECK_EQ(zone_allocator.allocate(5), allocated1);
CHECK_NE(zone_allocator.allocate(5), allocated2);
}
TEST_F(RecyclingZoneAllocatorTest, UseWithStdContainers) {
TestWithStdContainers<RecyclingZoneAllocator>();
}
} // namespace internal
} // namespace v8

View File

@ -0,0 +1,435 @@
// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/zone/zone-chunk-list.h"
#include "src/zone/accounting-allocator.h"
#include "src/zone/zone.h"
#include "test/unittests/test-utils.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace v8 {
namespace internal {
const size_t kItemCount = size_t(1) << 10;
class ZoneChunkListTest : public TestWithPlatform {};
TEST_F(ZoneChunkListTest, ForwardIterationTest) {
AccountingAllocator allocator;
Zone zone(&allocator, ZONE_NAME);
ZoneChunkList<uintptr_t> zone_chunk_list(&zone);
EXPECT_EQ(zone_chunk_list.begin(), zone_chunk_list.end());
for (size_t i = 0; i < kItemCount; ++i) {
zone_chunk_list.push_back(static_cast<uintptr_t>(i));
}
EXPECT_NE(zone_chunk_list.begin(), zone_chunk_list.end());
size_t count = 0;
for (uintptr_t item : zone_chunk_list) {
EXPECT_EQ(static_cast<size_t>(item), count);
count++;
}
EXPECT_EQ(count, kItemCount);
}
TEST_F(ZoneChunkListTest, ReverseIterationTest) {
AccountingAllocator allocator;
Zone zone(&allocator, ZONE_NAME);
ZoneChunkList<uintptr_t> zone_chunk_list(&zone);
EXPECT_EQ(zone_chunk_list.rbegin(), zone_chunk_list.rend());
for (size_t i = 0; i < kItemCount; ++i) {
zone_chunk_list.push_back(static_cast<uintptr_t>(i));
}
EXPECT_NE(zone_chunk_list.rbegin(), zone_chunk_list.rend());
size_t count = 0;
for (auto it = zone_chunk_list.rbegin(); it != zone_chunk_list.rend(); ++it) {
EXPECT_EQ(static_cast<size_t>(*it), kItemCount - count - 1);
count++;
}
EXPECT_EQ(count, kItemCount);
}
TEST_F(ZoneChunkListTest, PushFrontTest) {
AccountingAllocator allocator;
Zone zone(&allocator, ZONE_NAME);
ZoneChunkList<uintptr_t> zone_chunk_list(&zone);
for (size_t i = 0; i < kItemCount; ++i) {
zone_chunk_list.push_front(static_cast<uintptr_t>(i));
}
size_t count = 0;
for (uintptr_t item : zone_chunk_list) {
EXPECT_EQ(static_cast<size_t>(item), kItemCount - count - 1);
count++;
}
EXPECT_EQ(count, kItemCount);
}
TEST_F(ZoneChunkListTest, RewindTest) {
AccountingAllocator allocator;
Zone zone(&allocator, ZONE_NAME);
ZoneChunkList<uintptr_t> zone_chunk_list(&zone);
for (size_t i = 0; i < kItemCount; ++i) {
zone_chunk_list.push_back(static_cast<uintptr_t>(i));
}
zone_chunk_list.Rewind(42);
size_t count = 0;
for (uintptr_t item : zone_chunk_list) {
EXPECT_EQ(static_cast<size_t>(item), count);
count++;
}
EXPECT_EQ(count, 42u);
EXPECT_EQ(count, zone_chunk_list.size());
zone_chunk_list.Rewind(0);
count = 0;
for (uintptr_t item : zone_chunk_list) {
USE(item);
count++;
}
EXPECT_EQ(count, 0u);
EXPECT_EQ(count, zone_chunk_list.size());
zone_chunk_list.Rewind(100);
count = 0;
for (uintptr_t item : zone_chunk_list) {
EXPECT_EQ(static_cast<size_t>(item), count);
count++;
}
EXPECT_EQ(count, 0u);
EXPECT_EQ(count, zone_chunk_list.size());
}
TEST_F(ZoneChunkListTest, FindTest) {
AccountingAllocator allocator;
Zone zone(&allocator, ZONE_NAME);
ZoneChunkList<uintptr_t> zone_chunk_list(&zone);
for (size_t i = 0; i < kItemCount; ++i) {
zone_chunk_list.push_back(static_cast<uintptr_t>(i));
}
const size_t index = kItemCount / 2 + 42;
EXPECT_EQ(*zone_chunk_list.Find(index), static_cast<uintptr_t>(index));
*zone_chunk_list.Find(index) = 42;
EXPECT_EQ(*zone_chunk_list.Find(index), 42u);
}
TEST_F(ZoneChunkListTest, CopyToTest) {
AccountingAllocator allocator;
Zone zone(&allocator, ZONE_NAME);
ZoneChunkList<uintptr_t> zone_chunk_list(&zone);
for (size_t i = 0; i < kItemCount; ++i) {
zone_chunk_list.push_back(static_cast<uintptr_t>(i));
}
uintptr_t* array = zone.AllocateArray<uintptr_t>(kItemCount);
zone_chunk_list.CopyTo(array);
for (size_t i = 0; i < kItemCount; ++i) {
EXPECT_EQ(array[i], static_cast<uintptr_t>(i));
}
}
TEST_F(ZoneChunkListTest, SmallCopyToTest) {
AccountingAllocator allocator;
Zone zone(&allocator, ZONE_NAME);
ZoneChunkList<uint8_t> zone_chunk_list(&zone);
for (size_t i = 0; i < kItemCount; ++i) {
zone_chunk_list.push_back(static_cast<uint8_t>(i & 0xFF));
}
uint8_t* array = zone.AllocateArray<uint8_t>(kItemCount);
zone_chunk_list.CopyTo(array);
for (size_t i = 0; i < kItemCount; ++i) {
EXPECT_EQ(array[i], static_cast<uint8_t>(i & 0xFF));
}
}
struct Fubar {
size_t a_;
size_t b_;
};
TEST_F(ZoneChunkListTest, BigCopyToTest) {
AccountingAllocator allocator;
Zone zone(&allocator, ZONE_NAME);
ZoneChunkList<Fubar> zone_chunk_list(&zone);
for (size_t i = 0; i < kItemCount; ++i) {
zone_chunk_list.push_back({i, i + 5});
}
Fubar* array = zone.AllocateArray<Fubar>(kItemCount);
zone_chunk_list.CopyTo(array);
for (size_t i = 0; i < kItemCount; ++i) {
EXPECT_EQ(array[i].a_, i);
EXPECT_EQ(array[i].b_, i + 5);
}
}
void TestForwardIterationOfConstList(
const ZoneChunkList<uintptr_t>& zone_chunk_list) {
size_t count = 0;
for (uintptr_t item : zone_chunk_list) {
EXPECT_EQ(static_cast<size_t>(item), count);
count++;
}
EXPECT_EQ(count, kItemCount);
}
TEST_F(ZoneChunkListTest, ConstForwardIterationTest) {
AccountingAllocator allocator;
Zone zone(&allocator, ZONE_NAME);
ZoneChunkList<uintptr_t> zone_chunk_list(&zone);
for (size_t i = 0; i < kItemCount; ++i) {
zone_chunk_list.push_back(static_cast<uintptr_t>(i));
}
TestForwardIterationOfConstList(zone_chunk_list);
}
TEST_F(ZoneChunkListTest, RewindAndIterate) {
// Regression test for https://bugs.chromium.org/p/v8/issues/detail?id=7478
AccountingAllocator allocator;
Zone zone(&allocator, ZONE_NAME);
ZoneChunkList<int> zone_chunk_list(&zone);
// Fill the list enough so that it will contain 2 chunks.
int chunk_size = static_cast<int>(ZoneChunkList<int>::kInitialChunkCapacity);
for (int i = 0; i < chunk_size + 1; ++i) {
zone_chunk_list.push_back(i);
}
// Rewind and fill the first chunk again.
zone_chunk_list.Rewind();
for (int i = 0; i < chunk_size; ++i) {
zone_chunk_list.push_back(i);
}
std::vector<int> expected;
for (int i = 0; i < chunk_size; ++i) {
expected.push_back(i);
}
std::vector<int> got;
// Iterate. This used to not yield the expected result, since the end iterator
// was in a weird state, and the running iterator didn't reach it after the
// first chunk.
auto it = zone_chunk_list.begin();
while (it != zone_chunk_list.end()) {
int value = *it;
got.push_back(value);
++it;
}
CHECK_EQ(expected.size(), got.size());
for (size_t i = 0; i < expected.size(); ++i) {
CHECK_EQ(expected[i], got[i]);
}
}
TEST_F(ZoneChunkListTest, AdvanceZeroTest) {
AccountingAllocator allocator;
Zone zone(&allocator, ZONE_NAME);
ZoneChunkList<uintptr_t> zone_chunk_list(&zone);
for (size_t i = 0; i < kItemCount; ++i) {
zone_chunk_list.push_back(static_cast<uintptr_t>(i));
}
auto iterator_advance = zone_chunk_list.begin();
iterator_advance.Advance(0);
CHECK_EQ(iterator_advance, zone_chunk_list.begin());
}
TEST_F(ZoneChunkListTest, AdvancePartwayTest) {
AccountingAllocator allocator;
Zone zone(&allocator, ZONE_NAME);
ZoneChunkList<uintptr_t> zone_chunk_list(&zone);
for (size_t i = 0; i < kItemCount; ++i) {
zone_chunk_list.push_back(static_cast<uintptr_t>(i));
}
auto iterator_advance = zone_chunk_list.begin();
auto iterator_one_by_one = zone_chunk_list.begin();
iterator_advance.Advance(kItemCount / 2);
for (size_t i = 0; i < kItemCount / 2; ++i) {
++iterator_one_by_one;
}
CHECK_EQ(iterator_advance, iterator_one_by_one);
}
TEST_F(ZoneChunkListTest, AdvanceEndTest) {
AccountingAllocator allocator;
Zone zone(&allocator, ZONE_NAME);
ZoneChunkList<uintptr_t> zone_chunk_list(&zone);
for (size_t i = 0; i < kItemCount; ++i) {
zone_chunk_list.push_back(static_cast<uintptr_t>(i));
}
auto iterator_advance = zone_chunk_list.begin();
iterator_advance.Advance(kItemCount);
CHECK_EQ(iterator_advance, zone_chunk_list.end());
}
TEST_F(ZoneChunkListTest, FindOverChunkBoundary) {
AccountingAllocator allocator;
Zone zone(&allocator, ZONE_NAME);
ZoneChunkList<int> zone_chunk_list(&zone);
// Make sure we get two chunks.
int chunk_size = static_cast<int>(ZoneChunkList<int>::kInitialChunkCapacity);
for (int i = 0; i < chunk_size + 1; ++i) {
zone_chunk_list.push_back(i);
}
for (int i = 0; i < chunk_size + 1; ++i) {
CHECK_EQ(i, *zone_chunk_list.Find(i));
}
}
TEST_F(ZoneChunkListTest, SplitAt) {
AccountingAllocator allocator;
Zone zone(&allocator, ZONE_NAME);
ZoneChunkList<size_t> zone_chunk_list(&zone);
// Make sure we get two chunks.
for (size_t i = 0; i < kItemCount + 1; ++i) {
zone_chunk_list.push_back(i);
}
ZoneChunkList<size_t> split_end =
zone_chunk_list.SplitAt(zone_chunk_list.end());
CHECK(split_end.empty());
size_t count = 0;
for (size_t item : zone_chunk_list) {
CHECK_EQ(item, count);
count++;
}
CHECK_EQ(count, kItemCount + 1);
ZoneChunkList<size_t> split_begin =
zone_chunk_list.SplitAt(zone_chunk_list.begin());
CHECK(zone_chunk_list.empty());
count = 0;
for (size_t item : split_begin) {
CHECK_EQ(item, count);
count++;
}
CHECK_EQ(count, kItemCount + 1);
size_t mid = kItemCount / 2 + 42;
ZoneChunkList<size_t> split_mid = split_begin.SplitAt(split_begin.Find(mid));
count = 0;
for (size_t item : split_begin) {
CHECK_EQ(item, count);
count++;
}
CHECK_EQ(count, kItemCount / 2 + 42);
for (size_t item : split_mid) {
CHECK_EQ(item, count);
count++;
}
CHECK_EQ(count, kItemCount + 1);
}
TEST_F(ZoneChunkListTest, SplitAtLastChunk) {
AccountingAllocator allocator;
Zone zone(&allocator, ZONE_NAME);
ZoneChunkList<size_t> zone_chunk_list(&zone);
zone_chunk_list.push_back(0);
zone_chunk_list.push_back(1);
ZoneChunkList<size_t> split_last =
zone_chunk_list.SplitAt(++zone_chunk_list.begin());
CHECK_EQ(zone_chunk_list.size(), 1);
CHECK_EQ(zone_chunk_list.front(), 0);
CHECK_EQ(split_last.size(), 1);
CHECK_EQ(split_last.front(), 1);
}
TEST_F(ZoneChunkListTest, Append) {
AccountingAllocator allocator;
Zone zone(&allocator, ZONE_NAME);
ZoneChunkList<size_t> zone_chunk_list(&zone);
zone_chunk_list.push_back(0);
ZoneChunkList<size_t> other(&zone);
other.push_back(1);
zone_chunk_list.Append(other);
size_t count = 0;
for (size_t item : zone_chunk_list) {
CHECK_EQ(item, count++);
}
CHECK_EQ(count, zone_chunk_list.size());
CHECK(other.empty());
}
} // namespace internal
} // namespace v8

View File

@ -0,0 +1,250 @@
// Copyright 2023 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/zone/zone-compact-set.h"
#include "src/zone/zone.h"
#include "test/unittests/test-utils.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace v8 {
namespace internal {
struct HandleLike {
int* ptr;
};
bool operator==(HandleLike lhs, HandleLike rhs) { return lhs.ptr == rhs.ptr; }
template <>
struct ZoneCompactSetTraits<HandleLike> {
using handle_type = HandleLike;
using data_type = int;
static data_type* HandleToPointer(handle_type handle) { return handle.ptr; }
static handle_type PointerToHandle(data_type* ptr) { return HandleLike{ptr}; }
};
class ZoneCompactSetTest : public TestWithZone {
public:
HandleLike NewHandleLike(int value) {
return HandleLike{zone()->New<int>(value)};
}
};
TEST_F(ZoneCompactSetTest, Empty) {
ZoneCompactSet<HandleLike> zone_compact_set;
EXPECT_EQ(zone_compact_set.size(), 0u);
EXPECT_TRUE(zone_compact_set.is_empty());
}
TEST_F(ZoneCompactSetTest, SingleValue) {
ZoneCompactSet<HandleLike> zone_compact_set;
HandleLike handle = NewHandleLike(5);
zone_compact_set.insert(handle, zone());
EXPECT_EQ(zone_compact_set.size(), 1u);
EXPECT_FALSE(zone_compact_set.is_empty());
EXPECT_EQ(zone_compact_set.at(0), handle);
EXPECT_TRUE(zone_compact_set.contains(handle));
}
TEST_F(ZoneCompactSetTest, MultipleValue) {
ZoneCompactSet<HandleLike> zone_compact_set;
HandleLike handle1 = NewHandleLike(5);
HandleLike handle2 = NewHandleLike(8);
HandleLike handle3 = NewHandleLike(2);
HandleLike handle4 = NewHandleLike(1);
zone_compact_set.insert(handle1, zone());
zone_compact_set.insert(handle2, zone());
zone_compact_set.insert(handle3, zone());
zone_compact_set.insert(handle4, zone());
EXPECT_EQ(zone_compact_set.size(), 4u);
EXPECT_FALSE(zone_compact_set.is_empty());
EXPECT_TRUE(zone_compact_set.contains(handle1));
EXPECT_TRUE(zone_compact_set.contains(handle2));
EXPECT_TRUE(zone_compact_set.contains(handle3));
EXPECT_TRUE(zone_compact_set.contains(handle4));
}
TEST_F(ZoneCompactSetTest, DuplicateValue) {
ZoneCompactSet<HandleLike> zone_compact_set;
HandleLike handle1 = NewHandleLike(5);
HandleLike handle2 = NewHandleLike(8);
zone_compact_set.insert(handle1, zone());
zone_compact_set.insert(handle1, zone());
zone_compact_set.insert(handle2, zone());
zone_compact_set.insert(handle2, zone());
EXPECT_EQ(zone_compact_set.size(), 2u);
EXPECT_FALSE(zone_compact_set.is_empty());
EXPECT_TRUE(zone_compact_set.contains(handle1));
EXPECT_TRUE(zone_compact_set.contains(handle2));
}
TEST_F(ZoneCompactSetTest, RemoveSingleValue) {
ZoneCompactSet<HandleLike> zone_compact_set;
HandleLike handle1 = NewHandleLike(5);
zone_compact_set.insert(handle1, zone());
EXPECT_EQ(zone_compact_set.size(), 1u);
zone_compact_set.remove(handle1, zone());
EXPECT_EQ(zone_compact_set.size(), 0u);
EXPECT_TRUE(zone_compact_set.is_empty());
EXPECT_FALSE(zone_compact_set.contains(handle1));
}
TEST_F(ZoneCompactSetTest, RemoveFromMultipleValue) {
ZoneCompactSet<HandleLike> zone_compact_set;
HandleLike handle1 = NewHandleLike(5);
HandleLike handle2 = NewHandleLike(8);
zone_compact_set.insert(handle1, zone());
zone_compact_set.insert(handle2, zone());
EXPECT_EQ(zone_compact_set.size(), 2u);
zone_compact_set.remove(handle1, zone());
EXPECT_EQ(zone_compact_set.size(), 1u);
EXPECT_FALSE(zone_compact_set.is_empty());
EXPECT_FALSE(zone_compact_set.contains(handle1));
EXPECT_TRUE(zone_compact_set.contains(handle2));
}
TEST_F(ZoneCompactSetTest, RemoveFromEvenMoreMultipleValue) {
ZoneCompactSet<HandleLike> zone_compact_set;
HandleLike handle1 = NewHandleLike(5);
HandleLike handle2 = NewHandleLike(8);
HandleLike handle3 = NewHandleLike(1);
HandleLike handle4 = NewHandleLike(2);
zone_compact_set.insert(handle1, zone());
zone_compact_set.insert(handle2, zone());
zone_compact_set.insert(handle3, zone());
zone_compact_set.insert(handle4, zone());
EXPECT_EQ(zone_compact_set.size(), 4u);
zone_compact_set.remove(handle2, zone());
EXPECT_EQ(zone_compact_set.size(), 3u);
EXPECT_FALSE(zone_compact_set.is_empty());
EXPECT_TRUE(zone_compact_set.contains(handle1));
EXPECT_FALSE(zone_compact_set.contains(handle2));
EXPECT_TRUE(zone_compact_set.contains(handle3));
EXPECT_TRUE(zone_compact_set.contains(handle4));
}
TEST_F(ZoneCompactSetTest, RemoveNonExistent) {
ZoneCompactSet<HandleLike> zone_compact_set;
HandleLike handle1 = NewHandleLike(5);
HandleLike handle2 = NewHandleLike(8);
HandleLike handle3 = NewHandleLike(1);
zone_compact_set.insert(handle1, zone());
zone_compact_set.insert(handle2, zone());
zone_compact_set.remove(handle3, zone());
EXPECT_EQ(zone_compact_set.size(), 2u);
EXPECT_FALSE(zone_compact_set.is_empty());
EXPECT_TRUE(zone_compact_set.contains(handle1));
EXPECT_TRUE(zone_compact_set.contains(handle2));
EXPECT_FALSE(zone_compact_set.contains(handle3));
}
TEST_F(ZoneCompactSetTest, ContainsEmptySubset) {
ZoneCompactSet<HandleLike> zone_compact_set;
ZoneCompactSet<HandleLike> zone_compact_subset;
HandleLike handle1 = NewHandleLike(5);
HandleLike handle2 = NewHandleLike(8);
zone_compact_set.insert(handle1, zone());
zone_compact_set.insert(handle2, zone());
EXPECT_TRUE(zone_compact_set.contains(zone_compact_subset));
EXPECT_FALSE(zone_compact_subset.contains(zone_compact_set));
}
TEST_F(ZoneCompactSetTest, ContainsSingleElementSubset) {
ZoneCompactSet<HandleLike> zone_compact_set;
ZoneCompactSet<HandleLike> zone_compact_subset;
HandleLike handle1 = NewHandleLike(5);
HandleLike handle2 = NewHandleLike(8);
zone_compact_set.insert(handle1, zone());
zone_compact_set.insert(handle2, zone());
zone_compact_subset.insert(handle1, zone());
EXPECT_TRUE(zone_compact_set.contains(zone_compact_subset));
EXPECT_FALSE(zone_compact_subset.contains(zone_compact_set));
}
TEST_F(ZoneCompactSetTest, ContainsMultiElementSubset) {
ZoneCompactSet<HandleLike> zone_compact_set;
ZoneCompactSet<HandleLike> zone_compact_subset;
HandleLike handle1 = NewHandleLike(5);
HandleLike handle2 = NewHandleLike(8);
HandleLike handle3 = NewHandleLike(2);
HandleLike handle4 = NewHandleLike(1);
zone_compact_set.insert(handle1, zone());
zone_compact_set.insert(handle2, zone());
zone_compact_set.insert(handle3, zone());
zone_compact_set.insert(handle4, zone());
zone_compact_subset.insert(handle2, zone());
zone_compact_subset.insert(handle3, zone());
EXPECT_TRUE(zone_compact_set.contains(zone_compact_subset));
EXPECT_FALSE(zone_compact_subset.contains(zone_compact_set));
}
TEST_F(ZoneCompactSetTest, DoesNotContainsNonSubset) {
ZoneCompactSet<HandleLike> zone_compact_set;
ZoneCompactSet<HandleLike> zone_compact_other_set;
HandleLike handle1 = NewHandleLike(5);
HandleLike handle2 = NewHandleLike(8);
HandleLike handle3 = NewHandleLike(2);
HandleLike handle4 = NewHandleLike(1);
zone_compact_set.insert(handle1, zone());
zone_compact_set.insert(handle2, zone());
zone_compact_set.insert(handle3, zone());
zone_compact_other_set.insert(handle2, zone());
zone_compact_other_set.insert(handle4, zone());
EXPECT_FALSE(zone_compact_set.contains(zone_compact_other_set));
EXPECT_FALSE(zone_compact_other_set.contains(zone_compact_set));
}
} // namespace internal
} // namespace v8

View File

@ -0,0 +1,29 @@
// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/zone/zone.h"
#include "src/zone/accounting-allocator.h"
#include "test/unittests/test-utils.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace v8 {
namespace internal {
class ZoneTest : public TestWithPlatform {};
// This struct is just a type tag for Zone::Allocate<T>(size_t) call.
struct ZoneTestTag {};
TEST_F(ZoneTest, 8ByteAlignment) {
AccountingAllocator allocator;
Zone zone(&allocator, ZONE_NAME);
for (size_t i = 0; i < 16; ++i) {
ASSERT_EQ(reinterpret_cast<intptr_t>(zone.Allocate<ZoneTestTag>(i)) % 8, 0);
}
}
} // namespace internal
} // namespace v8

View File

@ -0,0 +1,373 @@
// Copyright 2023 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <optional>
#include "src/zone/zone-containers.h"
#include "test/unittests/test-utils.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace v8::internal {
template <class T>
class LiveSet {
public:
void Add(const T* new_entry) {
CHECK(!Contains(new_entry));
set_.insert(new_entry);
}
void Remove(const T* old_entry) {
CHECK(Contains(old_entry));
set_.erase(old_entry);
}
void CheckContainsAll(ZoneVector<T>& vector) {
CHECK_EQ(vector.size(), set_.size());
for (const T* m = vector.begin(); m != vector.end(); m++) {
CHECK(Contains(m));
}
}
void CheckEmpty() { CHECK_EQ(0, set_.size()); }
private:
bool Contains(const T* entry) {
// std::set::contains is a C++20 extension.
return set_.find(entry) != set_.end();
}
std::set<const T*> set_;
};
template <typename T>
LiveSet<T>& live_set() {
static LiveSet<T> static_live_set;
return static_live_set;
}
class Trivial {
public:
Trivial() : id_(0) {}
explicit Trivial(int id) : id_(id) {}
int id() const { return id_; }
private:
int id_;
};
static_assert(std::is_trivially_copyable_v<Trivial>);
template <>
class LiveSet<Trivial> {
public:
void Add(const Trivial* new_entry) { UNREACHABLE(); }
void Remove(const Trivial* old_entry) { UNREACHABLE(); }
void CheckContainsAll(ZoneVector<Trivial>&) {}
void CheckEmpty() {}
};
class CopyAssignable {
public:
CopyAssignable() : id_(0) { live_set<CopyAssignable>().Add(this); }
explicit CopyAssignable(int id) : id_(id) {
live_set<CopyAssignable>().Add(this);
}
CopyAssignable(const CopyAssignable& other) V8_NOEXCEPT : id_(other.id_) {
live_set<CopyAssignable>().Add(this);
}
~CopyAssignable() { live_set<CopyAssignable>().Remove(this); }
CopyAssignable& operator=(const CopyAssignable& other) V8_NOEXCEPT = default;
CopyAssignable(CopyAssignable&& other) = delete;
CopyAssignable& operator=(CopyAssignable&& other) = delete;
int id() const { return id_; }
private:
int id_;
};
static_assert(!std::is_trivially_copyable_v<CopyAssignable>);
static_assert(std::is_copy_assignable_v<CopyAssignable>);
static_assert(!std::is_move_assignable_v<CopyAssignable>);
class MoveAssignable {
public:
MoveAssignable() : id_(0) { live_set<MoveAssignable>().Add(this); }
explicit MoveAssignable(int id) : id_(id) {
live_set<MoveAssignable>().Add(this);
}
MoveAssignable(const MoveAssignable& other) V8_NOEXCEPT : id_(other.id_) {
live_set<MoveAssignable>().Add(this);
}
MoveAssignable(MoveAssignable&& other) V8_NOEXCEPT : id_(other.id_) {
live_set<MoveAssignable>().Add(this);
}
MoveAssignable& operator=(const MoveAssignable& other) = delete;
MoveAssignable& operator=(MoveAssignable&& other) V8_NOEXCEPT {
id_ = other.id_;
return *this;
}
~MoveAssignable() { live_set<MoveAssignable>().Remove(this); }
int id() const { return id_; }
private:
int id_;
};
static_assert(!std::is_trivially_copyable_v<MoveAssignable>);
static_assert(std::is_move_assignable_v<MoveAssignable>);
static_assert(!std::is_copy_assignable_v<MoveAssignable>);
class NotAssignable {
public:
NotAssignable() : id_(0) { live_set<NotAssignable>().Add(this); }
explicit NotAssignable(int id) : id_(id) {
live_set<NotAssignable>().Add(this);
}
NotAssignable(const NotAssignable& other) V8_NOEXCEPT : id_(other.id_) {
live_set<NotAssignable>().Add(this);
}
NotAssignable& operator=(const NotAssignable& other) = delete;
~NotAssignable() { live_set<NotAssignable>().Remove(this); }
NotAssignable(NotAssignable&& other) = delete;
NotAssignable& operator=(NotAssignable&& other) = delete;
int id() const { return id_; }
private:
int id_;
};
static_assert(!std::is_trivially_copyable_v<NotAssignable>);
static_assert(!std::is_copy_assignable_v<NotAssignable>);
static_assert(!std::is_move_assignable_v<NotAssignable>);
class ZoneVectorTest : public TestWithZone {
public:
template <class T>
void CheckConsistency(ZoneVector<T>& vector, std::initializer_list<int> ids) {
live_set<T>().CheckContainsAll(vector);
CHECK_EQ(vector.size(), ids.size());
auto it = ids.begin();
for (size_t i = 0; i < ids.size(); i++) {
CHECK_EQ(*it++, vector[i].id());
}
}
template <class T>
void Basic() {
{
// Constructor with definition.
ZoneVector<T> v(1, T(1), zone());
CheckConsistency(v, {1});
}
live_set<T>().CheckEmpty();
{
// Constructor with initializer list.
ZoneVector<T> v({T(1), T(2), T(3)}, zone());
CheckConsistency(v, {1, 2, 3});
}
live_set<T>().CheckEmpty();
{
std::optional<ZoneVector<T>> v1;
v1.emplace({T(1), T(2), T(3)}, zone());
CheckConsistency(v1.value(), {1, 2, 3});
{
// Copy assignment with growth.
ZoneVector<T> v2 = v1.value();
v1.reset();
CheckConsistency(v2, {1, 2, 3});
}
v1.emplace({T(1), T(2), T(3)}, zone());
CheckConsistency(v1.value(), {1, 2, 3});
// Copy assignment without growth.
ZoneVector<T> v3({T(4), T(5), T(6)}, zone());
v3 = v1.value();
v1.reset();
CheckConsistency(v3, {1, 2, 3});
// Move assignment.
{
ZoneVector<T> v4(std::move(v3));
CheckConsistency(v4, {1, 2, 3});
}
CheckConsistency(v3, {});
}
live_set<T>().CheckEmpty();
}
template <class T>
void Assign() {
{
// Assign with sufficient capacity.
ZoneVector<T> v({T(1), T(2), T(3)}, zone());
v.assign(2, T(4));
CheckConsistency(v, {4, 4});
// This time, capacity > size.
v.assign(3, T(5));
CheckConsistency(v, {5, 5, 5});
}
{
// Assign with capacity growth.
ZoneVector<T> v({T(1)}, zone());
v.assign(2, T(4));
CheckConsistency(v, {4, 4});
}
live_set<T>().CheckEmpty();
}
template <class T>
void Insert() {
// Check that we can insert (by iterator) in the right positions.
{
ZoneVector<T> v({T(2), T(4)}, zone());
{
T src1[] = {T(1)};
T src3[] = {T(3)};
T src5[] = {T(5)};
v.insert(&v.at(0), src1, std::end(src1));
v.insert(&v.at(2), src3, std::end(src3));
v.insert(v.end(), src5, std::end(src5));
}
CheckConsistency(v, {1, 2, 3, 4, 5});
}
// Check that we can insert (by count) in the right positions.
{
ZoneVector<T> v({T(2), T(4)}, zone());
v.insert(&v.at(0), 1, T(1));
v.insert(&v.at(2), 1, T(3));
v.insert(v.end(), 1, T(5));
CheckConsistency(v, {1, 2, 3, 4, 5});
}
// Test the "insufficient capacity" case in PrepareForInsertion.
{
ZoneVector<T> v(zone());
CHECK_EQ(0, v.capacity());
v.insert(v.begin(), 1, T(5));
CheckConsistency(v, {5});
{
T src[] = {T(1), T(2), T(3), T(4)};
v.insert(v.begin(), src, std::end(src));
}
CheckConsistency(v, {1, 2, 3, 4, 5});
}
// Test "case 1" of sufficient capacity in PrepareForInsertion.
{
ZoneVector<T> v({T(1), T(2), T(3), T(4), T(5)}, zone());
v.reserve(10);
CHECK_EQ(10, v.capacity());
CheckConsistency(v, {1, 2, 3, 4, 5});
{
T src[] = {T(11), T(12), T(13), T(14)};
v.insert(&v.at(3), src, std::end(src));
}
CheckConsistency(v, {1, 2, 3, 11, 12, 13, 14, 4, 5});
}
// Test "case 2" of sufficient capacity in PrepareForInsertion.
{
ZoneVector<T> v({T(1), T(2), T(3), T(4), T(5)}, zone());
v.reserve(10);
{
T src[] = {T(11), T(12)};
v.insert(&v.at(2), src, std::end(src));
}
CheckConsistency(v, {1, 2, 11, 12, 3, 4, 5});
}
live_set<T>().CheckEmpty();
// For good measure, test the edge case where we're inserting exactly
// as many elements as we're moving.
{
ZoneVector<T> v({T(1), T(2), T(3), T(4)}, zone());
v.reserve(10);
{
T src[] = {T(11), T(12)};
v.insert(&v.at(2), src, std::end(src));
}
}
}
template <class T>
void Erase() {
// Erase one element.
{
ZoneVector<T> v({T(1), T(2), T(3)}, zone());
v.erase(&v.at(1));
CheckConsistency(v, {1, 3});
}
// Erase a range.
{
ZoneVector<T> v({T(1), T(2), T(3), T(4)}, zone());
v.erase(&v.at(1), &v.at(3));
CheckConsistency(v, {1, 4});
}
// Erase first element.
{
ZoneVector<T> v({T(1), T(2), T(3)}, zone());
v.erase(v.begin());
CheckConsistency(v, {2, 3});
}
// Erase last element.
{
ZoneVector<T> v({T(1), T(2), T(3)}, zone());
v.erase(&v.at(2));
CheckConsistency(v, {1, 2});
}
// Erase nothing (empty range).
{
ZoneVector<T> v({T(1), T(2), T(3)}, zone());
v.erase(v.begin(), v.begin());
CheckConsistency(v, {1, 2, 3});
v.erase(&v.at(1), &v.at(1));
CheckConsistency(v, {1, 2, 3});
v.erase(v.end(), v.end());
CheckConsistency(v, {1, 2, 3});
}
live_set<T>().CheckEmpty();
}
};
TEST_F(ZoneVectorTest, Basic) {
Basic<Trivial>();
Basic<CopyAssignable>();
Basic<MoveAssignable>();
Basic<NotAssignable>();
}
TEST_F(ZoneVectorTest, Assign) {
Assign<Trivial>();
Assign<CopyAssignable>();
Assign<MoveAssignable>();
Assign<NotAssignable>();
}
TEST_F(ZoneVectorTest, Insert) {
Insert<Trivial>();
Insert<CopyAssignable>();
Insert<MoveAssignable>();
Insert<NotAssignable>();
}
TEST_F(ZoneVectorTest, Erase) {
Erase<Trivial>();
Erase<CopyAssignable>();
Erase<MoveAssignable>();
Erase<NotAssignable>();
}
} // namespace v8::internal