Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nodejs/node.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/test/unittests/heap/cppgc/heap-page-unittest.cc')
-rw-r--r--deps/v8/test/unittests/heap/cppgc/heap-page-unittest.cc274
1 files changed, 274 insertions, 0 deletions
diff --git a/deps/v8/test/unittests/heap/cppgc/heap-page-unittest.cc b/deps/v8/test/unittests/heap/cppgc/heap-page-unittest.cc
new file mode 100644
index 00000000000..fa8897128de
--- /dev/null
+++ b/deps/v8/test/unittests/heap/cppgc/heap-page-unittest.cc
@@ -0,0 +1,274 @@
+// Copyright 2020 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/heap/cppgc/heap-page.h"
+
+#include <algorithm>
+
+#include "include/cppgc/allocation.h"
+#include "include/cppgc/internal/accessors.h"
+#include "include/cppgc/persistent.h"
+#include "src/base/macros.h"
+#include "src/heap/cppgc/globals.h"
+#include "src/heap/cppgc/heap-object-header-inl.h"
+#include "src/heap/cppgc/heap-object-header.h"
+#include "src/heap/cppgc/page-memory-inl.h"
+#include "src/heap/cppgc/raw-heap.h"
+#include "test/unittests/heap/cppgc/tests.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace cppgc {
+namespace internal {
+
+namespace {
+
+class PageTest : public testing::TestWithHeap {
+ public:
+ RawHeap& GetRawHeap() { return Heap::From(GetHeap())->raw_heap(); }
+};
+
+template <size_t Size>
+class GCed : public GarbageCollected<GCed<Size>> {
+ public:
+ virtual void Trace(cppgc::Visitor*) const {}
+ char array[Size];
+};
+
+} // namespace
+
+TEST_F(PageTest, GetHeapForAllocatedObject) {
+ auto* gced = MakeGarbageCollected<GCed<1>>(GetHeap());
+ EXPECT_EQ(GetHeap(), GetHeapFromPayload(gced));
+}
+
+TEST_F(PageTest, SpaceIndexing) {
+ RawHeap& heap = GetRawHeap();
+ size_t space = 0u;
+ for (const auto& ptr : heap) {
+ EXPECT_EQ(&heap, ptr.get()->raw_heap());
+ EXPECT_EQ(space, ptr->index());
+ ++space;
+ }
+ EXPECT_GE(space, RawHeap::kNumberOfRegularSpaces);
+}
+
+TEST_F(PageTest, PredefinedSpaces) {
+ using SpaceType = RawHeap::RegularSpaceType;
+ RawHeap& heap = GetRawHeap();
+ {
+ auto* gced = MakeGarbageCollected<GCed<1>>(GetHeap());
+ BaseSpace* space = NormalPage::FromPayload(gced)->space();
+ EXPECT_EQ(heap.Space(SpaceType::kNormal1), space);
+ EXPECT_EQ(0u, space->index());
+ EXPECT_FALSE(space->is_large());
+ }
+ {
+ auto* gced = MakeGarbageCollected<GCed<32>>(GetHeap());
+ BaseSpace* space = NormalPage::FromPayload(gced)->space();
+ EXPECT_EQ(heap.Space(SpaceType::kNormal2), space);
+ EXPECT_EQ(1u, space->index());
+ EXPECT_FALSE(space->is_large());
+ }
+ {
+ auto* gced = MakeGarbageCollected<GCed<64>>(GetHeap());
+ BaseSpace* space = NormalPage::FromPayload(gced)->space();
+ EXPECT_EQ(heap.Space(SpaceType::kNormal3), space);
+ EXPECT_EQ(2u, space->index());
+ EXPECT_FALSE(space->is_large());
+ }
+ {
+ auto* gced = MakeGarbageCollected<GCed<128>>(GetHeap());
+ BaseSpace* space = NormalPage::FromPayload(gced)->space();
+ EXPECT_EQ(heap.Space(SpaceType::kNormal4), space);
+ EXPECT_EQ(3u, space->index());
+ EXPECT_FALSE(space->is_large());
+ }
+ {
+ auto* gced =
+ MakeGarbageCollected<GCed<2 * kLargeObjectSizeThreshold>>(GetHeap());
+ BaseSpace* space = NormalPage::FromPayload(gced)->space();
+ EXPECT_EQ(heap.Space(SpaceType::kLarge), space);
+ EXPECT_EQ(4u, space->index());
+ EXPECT_TRUE(space->is_large());
+ }
+}
+
+TEST_F(PageTest, NormalPageIndexing) {
+ using SpaceType = RawHeap::RegularSpaceType;
+ constexpr size_t kExpectedNumberOfPages = 10u;
+ constexpr size_t kObjectSize = 8u;
+ using Type = GCed<kObjectSize>;
+ static const size_t kNumberOfObjects =
+ (kExpectedNumberOfPages * NormalPage::PayloadSize() /
+ (sizeof(Type) + sizeof(HeapObjectHeader))) -
+ kExpectedNumberOfPages;
+
+ std::vector<Persistent<Type>> persistents(kNumberOfObjects);
+ for (auto& p : persistents) {
+ p = MakeGarbageCollected<Type>(GetHeap());
+ }
+
+ const RawHeap& heap = GetRawHeap();
+ const BaseSpace* space = heap.Space(SpaceType::kNormal1);
+ EXPECT_EQ(kExpectedNumberOfPages, space->size());
+
+ size_t page_n = 0;
+ for (const BasePage* page : *space) {
+ EXPECT_FALSE(page->is_large());
+ EXPECT_EQ(space, page->space());
+ ++page_n;
+ }
+ EXPECT_EQ(page_n, space->size());
+}
+
+TEST_F(PageTest, LargePageIndexing) {
+ using SpaceType = RawHeap::RegularSpaceType;
+ constexpr size_t kExpectedNumberOfPages = 10u;
+ constexpr size_t kObjectSize = 2 * kLargeObjectSizeThreshold;
+ using Type = GCed<kObjectSize>;
+ const size_t kNumberOfObjects = kExpectedNumberOfPages;
+
+ std::vector<Persistent<Type>> persistents(kNumberOfObjects);
+ for (auto& p : persistents) {
+ p = MakeGarbageCollected<Type>(GetHeap());
+ }
+
+ const RawHeap& heap = GetRawHeap();
+ const BaseSpace* space = heap.Space(SpaceType::kLarge);
+ EXPECT_EQ(kExpectedNumberOfPages, space->size());
+
+ size_t page_n = 0;
+ for (const BasePage* page : *space) {
+ EXPECT_TRUE(page->is_large());
+ ++page_n;
+ }
+ EXPECT_EQ(page_n, space->size());
+}
+
+TEST_F(PageTest, HeapObjectHeaderOnBasePageIndexing) {
+ constexpr size_t kObjectSize = 8;
+ using Type = GCed<kObjectSize>;
+ const size_t kNumberOfObjects =
+ NormalPage::PayloadSize() / (sizeof(Type) + sizeof(HeapObjectHeader));
+ const size_t kLeftSpace =
+ NormalPage::PayloadSize() % (sizeof(Type) + sizeof(HeapObjectHeader));
+
+ std::vector<Persistent<Type>> persistents(kNumberOfObjects);
+ for (auto& p : persistents) {
+ p = MakeGarbageCollected<Type>(GetHeap());
+ }
+
+ const auto* page =
+ static_cast<NormalPage*>(BasePage::FromPayload(persistents[0].Get()));
+ size_t size = 0;
+ size_t num = 0;
+ for (const HeapObjectHeader& header : *page) {
+ EXPECT_EQ(reinterpret_cast<Address>(persistents[num].Get()),
+ header.Payload());
+ size += header.GetSize();
+ ++num;
+ }
+ EXPECT_EQ(num, persistents.size());
+ EXPECT_EQ(size + kLeftSpace, NormalPage::PayloadSize());
+}
+
+TEST_F(PageTest, HeapObjectHeaderOnLargePageIndexing) {
+ constexpr size_t kObjectSize = 2 * kLargeObjectSizeThreshold;
+ using Type = GCed<kObjectSize>;
+ auto* gced = MakeGarbageCollected<Type>(GetHeap());
+
+ const auto* page = static_cast<LargePage*>(BasePage::FromPayload(gced));
+ const size_t expected_payload_size =
+ RoundUp(sizeof(Type) + sizeof(HeapObjectHeader), kAllocationGranularity);
+ EXPECT_EQ(expected_payload_size, page->PayloadSize());
+
+ const HeapObjectHeader* header = page->ObjectHeader();
+ EXPECT_EQ(reinterpret_cast<Address>(gced), header->Payload());
+}
+
+TEST_F(PageTest, NormalPageCreationDestruction) {
+ RawHeap& heap = GetRawHeap();
+ const PageBackend* backend = Heap::From(GetHeap())->page_backend();
+ auto* space = static_cast<NormalPageSpace*>(
+ heap.Space(RawHeap::RegularSpaceType::kNormal1));
+ auto* page = NormalPage::Create(space);
+ EXPECT_NE(space->end(), std::find(space->begin(), space->end(), page));
+ EXPECT_TRUE(
+ space->free_list().Contains({page->PayloadStart(), page->PayloadSize()}));
+ EXPECT_NE(nullptr, backend->Lookup(page->PayloadStart()));
+
+ space->free_list().Clear();
+ EXPECT_FALSE(
+ space->free_list().Contains({page->PayloadStart(), page->PayloadSize()}));
+ space->RemovePage(page);
+ EXPECT_EQ(space->end(), std::find(space->begin(), space->end(), page));
+ NormalPage::Destroy(page);
+ EXPECT_EQ(nullptr, backend->Lookup(page->PayloadStart()));
+}
+
+TEST_F(PageTest, LargePageCreationDestruction) {
+ constexpr size_t kObjectSize = 2 * kLargeObjectSizeThreshold;
+ RawHeap& heap = GetRawHeap();
+ const PageBackend* backend = Heap::From(GetHeap())->page_backend();
+ auto* space = static_cast<LargePageSpace*>(
+ heap.Space(RawHeap::RegularSpaceType::kLarge));
+ auto* page = LargePage::Create(space, kObjectSize);
+ EXPECT_NE(space->end(), std::find(space->begin(), space->end(), page));
+ EXPECT_NE(nullptr, backend->Lookup(page->PayloadStart()));
+
+ space->RemovePage(page);
+ EXPECT_EQ(space->end(), std::find(space->begin(), space->end(), page));
+ LargePage::Destroy(page);
+ EXPECT_EQ(nullptr, backend->Lookup(page->PayloadStart()));
+}
+
+#if DEBUG
+TEST_F(PageTest, UnsweptPageDestruction) {
+ RawHeap& heap = GetRawHeap();
+ {
+ auto* space = static_cast<NormalPageSpace*>(
+ heap.Space(RawHeap::RegularSpaceType::kNormal1));
+ auto* page = NormalPage::Create(space);
+ EXPECT_DEATH_IF_SUPPORTED(NormalPage::Destroy(page), "");
+ }
+ {
+ auto* space = static_cast<LargePageSpace*>(
+ heap.Space(RawHeap::RegularSpaceType::kLarge));
+ auto* page = LargePage::Create(space, 2 * kLargeObjectSizeThreshold);
+ EXPECT_DEATH_IF_SUPPORTED(LargePage::Destroy(page), "");
+ // Detach page and really destroy page in the parent process so that sweeper
+ // doesn't consider it.
+ space->RemovePage(page);
+ LargePage::Destroy(page);
+ }
+}
+#endif
+
+TEST_F(PageTest, ObjectHeaderFromInnerAddress) {
+ {
+ auto* object = MakeGarbageCollected<GCed<64>>(GetHeap());
+ const HeapObjectHeader& expected = HeapObjectHeader::FromPayload(object);
+
+ for (auto* inner_ptr = reinterpret_cast<ConstAddress>(object);
+ inner_ptr < reinterpret_cast<ConstAddress>(object + 1); ++inner_ptr) {
+ const HeapObjectHeader* hoh =
+ BasePage::FromPayload(object)->ObjectHeaderFromInnerAddress(
+ inner_ptr);
+ EXPECT_EQ(&expected, hoh);
+ }
+ }
+ {
+ auto* object =
+ MakeGarbageCollected<GCed<2 * kLargeObjectSizeThreshold>>(GetHeap());
+ const HeapObjectHeader& expected = HeapObjectHeader::FromPayload(object);
+
+ const HeapObjectHeader* hoh =
+ BasePage::FromPayload(object)->ObjectHeaderFromInnerAddress(
+ reinterpret_cast<ConstAddress>(object) + kLargeObjectSizeThreshold);
+ EXPECT_EQ(&expected, hoh);
+ }
+}
+
+} // namespace internal
+} // namespace cppgc