4d5ab15dc4
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}
247 lines
7.3 KiB
C++
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
|