v8/test/unittests/heap/cppgc/custom-spaces-unittest.cc
Omer Katz 4d5ab15dc4 cppgc: Mark custom spaces as compactable
To support compaction of backing stores in blink, we need to distinguish
custom spaces holding backing stores from other custom spaces.
Custom space compactablity is explicitly declared as an enum value and
propagated to BaseSpace as a bool flag.

Note that even if/when general compaction is implemented/enabled for
normal pages we will still need such a marking for supporting
non-compactable custom spaces.

Bug: v8:10990
Change-Id: I165a0268ded121e91399834a4091e88e57f2565c
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2449973
Commit-Queue: Omer Katz <omerkatz@chromium.org>
Reviewed-by: Michael Lippautz <mlippautz@chromium.org>
Cr-Commit-Position: refs/heads/master@{#70345}
2020-10-06 14:59:22 +00:00

247 lines
7.3 KiB
C++

// 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 "include/cppgc/allocation.h"
#include "include/cppgc/custom-space.h"
#include "src/heap/cppgc/heap-page.h"
#include "src/heap/cppgc/raw-heap.h"
#include "test/unittests/heap/cppgc/tests.h"
namespace cppgc {
class CustomSpace1 : public CustomSpace<CustomSpace1> {
public:
static constexpr size_t kSpaceIndex = 0;
};
class CustomSpace2 : public CustomSpace<CustomSpace2> {
public:
static constexpr size_t kSpaceIndex = 1;
};
namespace internal {
namespace {
size_t g_destructor_callcount;
class TestWithHeapWithCustomSpaces : public testing::TestWithPlatform {
protected:
TestWithHeapWithCustomSpaces() {
Heap::HeapOptions options;
options.custom_spaces.emplace_back(std::make_unique<CustomSpace1>());
options.custom_spaces.emplace_back(std::make_unique<CustomSpace2>());
heap_ = Heap::Create(platform_, std::move(options));
g_destructor_callcount = 0;
}
void PreciseGC() {
heap_->ForceGarbageCollectionSlow(
::testing::UnitTest::GetInstance()->current_test_info()->name(),
"Testing", cppgc::Heap::StackState::kNoHeapPointers);
}
cppgc::Heap* GetHeap() const { return heap_.get(); }
private:
std::unique_ptr<cppgc::Heap> heap_;
};
class RegularGCed final : public GarbageCollected<RegularGCed> {
public:
void Trace(Visitor*) const {}
};
class CustomGCed1 final : public GarbageCollected<CustomGCed1> {
public:
~CustomGCed1() { g_destructor_callcount++; }
void Trace(Visitor*) const {}
};
class CustomGCed2 final : public GarbageCollected<CustomGCed2> {
public:
~CustomGCed2() { g_destructor_callcount++; }
void Trace(Visitor*) const {}
};
class CustomGCedBase : public GarbageCollected<CustomGCedBase> {
public:
void Trace(Visitor*) const {}
};
class CustomGCedFinal1 final : public CustomGCedBase {
public:
~CustomGCedFinal1() { g_destructor_callcount++; }
};
class CustomGCedFinal2 final : public CustomGCedBase {
public:
~CustomGCedFinal2() { g_destructor_callcount++; }
};
} // namespace
} // namespace internal
template <>
struct SpaceTrait<internal::CustomGCed1> {
using Space = CustomSpace1;
};
template <>
struct SpaceTrait<internal::CustomGCed2> {
using Space = CustomSpace2;
};
template <typename T>
struct SpaceTrait<
T, std::enable_if_t<std::is_base_of<internal::CustomGCedBase, T>::value>> {
using Space = CustomSpace1;
};
namespace internal {
TEST_F(TestWithHeapWithCustomSpaces, AllocateOnCustomSpaces) {
auto* regular =
MakeGarbageCollected<RegularGCed>(GetHeap()->GetAllocationHandle());
auto* custom1 =
MakeGarbageCollected<CustomGCed1>(GetHeap()->GetAllocationHandle());
auto* custom2 =
MakeGarbageCollected<CustomGCed2>(GetHeap()->GetAllocationHandle());
EXPECT_EQ(RawHeap::kNumberOfRegularSpaces,
NormalPage::FromPayload(custom1)->space()->index());
EXPECT_EQ(RawHeap::kNumberOfRegularSpaces + 1,
NormalPage::FromPayload(custom2)->space()->index());
EXPECT_EQ(static_cast<size_t>(RawHeap::RegularSpaceType::kNormal1),
NormalPage::FromPayload(regular)->space()->index());
}
TEST_F(TestWithHeapWithCustomSpaces,
AllocateOnCustomSpacesSpecifiedThroughBase) {
auto* regular =
MakeGarbageCollected<RegularGCed>(GetHeap()->GetAllocationHandle());
auto* custom1 =
MakeGarbageCollected<CustomGCedFinal1>(GetHeap()->GetAllocationHandle());
auto* custom2 =
MakeGarbageCollected<CustomGCedFinal2>(GetHeap()->GetAllocationHandle());
EXPECT_EQ(RawHeap::kNumberOfRegularSpaces,
NormalPage::FromPayload(custom1)->space()->index());
EXPECT_EQ(RawHeap::kNumberOfRegularSpaces,
NormalPage::FromPayload(custom2)->space()->index());
EXPECT_EQ(static_cast<size_t>(RawHeap::RegularSpaceType::kNormal1),
NormalPage::FromPayload(regular)->space()->index());
}
TEST_F(TestWithHeapWithCustomSpaces, SweepCustomSpace) {
MakeGarbageCollected<CustomGCedFinal1>(GetHeap()->GetAllocationHandle());
MakeGarbageCollected<CustomGCedFinal2>(GetHeap()->GetAllocationHandle());
MakeGarbageCollected<CustomGCed1>(GetHeap()->GetAllocationHandle());
MakeGarbageCollected<CustomGCed2>(GetHeap()->GetAllocationHandle());
EXPECT_EQ(0u, g_destructor_callcount);
PreciseGC();
EXPECT_EQ(4u, g_destructor_callcount);
}
} // namespace internal
// Test custom space compactability.
class CompactableCustomSpace : public CustomSpace<CompactableCustomSpace> {
public:
static constexpr size_t kSpaceIndex = 0;
static constexpr bool kSupportsCompaction = true;
};
class NotCompactableCustomSpace
: public CustomSpace<NotCompactableCustomSpace> {
public:
static constexpr size_t kSpaceIndex = 1;
static constexpr bool kSupportsCompaction = false;
};
class DefaultCompactableCustomSpace
: public CustomSpace<DefaultCompactableCustomSpace> {
public:
static constexpr size_t kSpaceIndex = 2;
// By default space are not compactable.
};
namespace internal {
namespace {
class TestWithHeapWithCompactableCustomSpaces
: public testing::TestWithPlatform {
protected:
TestWithHeapWithCompactableCustomSpaces() {
Heap::HeapOptions options;
options.custom_spaces.emplace_back(
std::make_unique<CompactableCustomSpace>());
options.custom_spaces.emplace_back(
std::make_unique<NotCompactableCustomSpace>());
options.custom_spaces.emplace_back(
std::make_unique<DefaultCompactableCustomSpace>());
heap_ = Heap::Create(platform_, std::move(options));
g_destructor_callcount = 0;
}
void PreciseGC() {
heap_->ForceGarbageCollectionSlow("TestWithHeapWithCompactableCustomSpaces",
"Testing",
cppgc::Heap::StackState::kNoHeapPointers);
}
cppgc::Heap* GetHeap() const { return heap_.get(); }
private:
std::unique_ptr<cppgc::Heap> heap_;
};
class CompactableGCed final : public GarbageCollected<CompactableGCed> {
public:
void Trace(Visitor*) const {}
};
class NotCompactableGCed final : public GarbageCollected<NotCompactableGCed> {
public:
void Trace(Visitor*) const {}
};
class DefaultCompactableGCed final
: public GarbageCollected<DefaultCompactableGCed> {
public:
void Trace(Visitor*) const {}
};
} // namespace
} // namespace internal
template <>
struct SpaceTrait<internal::CompactableGCed> {
using Space = CompactableCustomSpace;
};
template <>
struct SpaceTrait<internal::NotCompactableGCed> {
using Space = NotCompactableCustomSpace;
};
template <>
struct SpaceTrait<internal::DefaultCompactableGCed> {
using Space = DefaultCompactableCustomSpace;
};
namespace internal {
TEST_F(TestWithHeapWithCompactableCustomSpaces,
AllocateOnCompactableCustomSpaces) {
auto* compactable =
MakeGarbageCollected<CompactableGCed>(GetHeap()->GetAllocationHandle());
auto* not_compactable = MakeGarbageCollected<NotCompactableGCed>(
GetHeap()->GetAllocationHandle());
auto* default_compactable = MakeGarbageCollected<DefaultCompactableGCed>(
GetHeap()->GetAllocationHandle());
EXPECT_TRUE(NormalPage::FromPayload(compactable)->space()->is_compactable());
EXPECT_FALSE(
NormalPage::FromPayload(not_compactable)->space()->is_compactable());
EXPECT_FALSE(
NormalPage::FromPayload(default_compactable)->space()->is_compactable());
}
} // namespace internal
} // namespace cppgc