cppgc: Introduce AllocationHandle
Unified heap support in V8 requires having another (at least internal) heap that implements a unfied garbage collection strategy. This will not re-use the already existing cppgc::Heap because there should be no way in creating such a heap externally or scheduling stand-alone garbage collections. In order to have a common token, this CL introduces AllocationHandle which can be passed to MakeGarbageCollected to allocate C++ objects. V8 (soon) and the stand-alone heap both have methods to retrieve such a handle. This works around a problem with creating diamond class hierarchies when a base class would be exposed on the public API level. Fast paths for Blink are still possible because allocation handles can be cached the same way (e.g. global, or TLS) as a heap can be cached. Tbr: yangguo@chromium.org Bug: chromium:1056170 Change-Id: I8e9472a2c24ef82d1178953e8429b1fd8a2344bc Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2238027 Commit-Queue: Michael Lippautz <mlippautz@chromium.org> Reviewed-by: Omer Katz <omerkatz@chromium.org> Reviewed-by: Ulan Degenbaev <ulan@chromium.org> Cr-Commit-Position: refs/heads/master@{#68310}
This commit is contained in:
parent
4559bd694f
commit
935d915186
1
BUILD.gn
1
BUILD.gn
@ -4133,7 +4133,6 @@ v8_source_set("cppgc_base") {
|
||||
"src/heap/cppgc/gc-invoker.h",
|
||||
"src/heap/cppgc/heap-growing.cc",
|
||||
"src/heap/cppgc/heap-growing.h",
|
||||
"src/heap/cppgc/heap-inl.h",
|
||||
"src/heap/cppgc/heap-object-header-inl.h",
|
||||
"src/heap/cppgc/heap-object-header.cc",
|
||||
"src/heap/cppgc/heap-object-header.h",
|
||||
|
@ -11,7 +11,6 @@
|
||||
|
||||
#include "cppgc/custom-space.h"
|
||||
#include "cppgc/garbage-collected.h"
|
||||
#include "cppgc/heap.h"
|
||||
#include "cppgc/internal/api-constants.h"
|
||||
#include "cppgc/internal/gc-info.h"
|
||||
|
||||
@ -20,6 +19,15 @@ namespace cppgc {
|
||||
template <typename T>
|
||||
class MakeGarbageCollectedTraitBase;
|
||||
|
||||
namespace internal {
|
||||
class ObjectAllocator;
|
||||
} // namespace internal
|
||||
|
||||
/**
|
||||
* AllocationHandle is used to allocate garbage-collected objects.
|
||||
*/
|
||||
class AllocationHandle;
|
||||
|
||||
namespace internal {
|
||||
|
||||
class V8_EXPORT MakeGarbageCollectedTraitInternal {
|
||||
@ -36,9 +44,12 @@ class V8_EXPORT MakeGarbageCollectedTraitInternal {
|
||||
atomic_mutable_bitfield->store(value, std::memory_order_release);
|
||||
}
|
||||
|
||||
static void* Allocate(cppgc::Heap* heap, size_t size, GCInfoIndex index);
|
||||
static void* Allocate(cppgc::Heap* heap, size_t size, GCInfoIndex index,
|
||||
CustomSpaceIndex space_index);
|
||||
static void* Allocate(
|
||||
cppgc::AllocationHandle& handle, // NOLINT(runtime/references)
|
||||
size_t size, GCInfoIndex index);
|
||||
static void* Allocate(
|
||||
cppgc::AllocationHandle& handle, // NOLINT(runtime/references)
|
||||
size_t size, GCInfoIndex index, CustomSpaceIndex space_index);
|
||||
|
||||
friend class HeapObjectHeader;
|
||||
};
|
||||
@ -58,22 +69,26 @@ class MakeGarbageCollectedTraitBase
|
||||
private:
|
||||
template <typename U, typename CustomSpace>
|
||||
struct SpacePolicy {
|
||||
static void* Allocate(Heap* heap, size_t size) {
|
||||
static void* Allocate(
|
||||
AllocationHandle& handle, // NOLINT(runtime/references)
|
||||
size_t size) {
|
||||
// Custom space.
|
||||
static_assert(std::is_base_of<CustomSpaceBase, CustomSpace>::value,
|
||||
"Custom space must inherit from CustomSpaceBase.");
|
||||
return internal::MakeGarbageCollectedTraitInternal::Allocate(
|
||||
heap, size, internal::GCInfoTrait<T>::Index(),
|
||||
handle, size, internal::GCInfoTrait<T>::Index(),
|
||||
CustomSpace::kSpaceIndex);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename U>
|
||||
struct SpacePolicy<U, void> {
|
||||
static void* Allocate(Heap* heap, size_t size) {
|
||||
static void* Allocate(
|
||||
AllocationHandle& handle, // NOLINT(runtime/references)
|
||||
size_t size) {
|
||||
// Default space.
|
||||
return internal::MakeGarbageCollectedTraitInternal::Allocate(
|
||||
heap, size, internal::GCInfoTrait<T>::Index());
|
||||
handle, size, internal::GCInfoTrait<T>::Index());
|
||||
}
|
||||
};
|
||||
|
||||
@ -81,12 +96,15 @@ class MakeGarbageCollectedTraitBase
|
||||
/**
|
||||
* Allocates memory for an object of type T.
|
||||
*
|
||||
* \param heap The heap to allocate this object on.
|
||||
* \param handle AllocationHandle identifying the heap to allocate the object
|
||||
* on.
|
||||
* \param size The size that should be reserved for the object.
|
||||
* \returns the memory to construct an object of type T on.
|
||||
*/
|
||||
static void* Allocate(Heap* heap, size_t size) {
|
||||
return SpacePolicy<T, typename SpaceTrait<T>::Space>::Allocate(heap, size);
|
||||
static void* Allocate(AllocationHandle& handle, // NOLINT(runtime/references)
|
||||
size_t size) {
|
||||
return SpacePolicy<T, typename SpaceTrait<T>::Space>::Allocate(handle,
|
||||
size);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -115,14 +133,16 @@ template <typename T>
|
||||
class MakeGarbageCollectedTrait : public MakeGarbageCollectedTraitBase<T> {
|
||||
public:
|
||||
template <typename... Args>
|
||||
static T* Call(Heap* heap, Args&&... args) {
|
||||
static T* Call(AllocationHandle& handle, // NOLINT(runtime/references)
|
||||
Args&&... args) {
|
||||
static_assert(internal::IsGarbageCollectedType<T>::value,
|
||||
"T needs to be a garbage collected object");
|
||||
static_assert(
|
||||
!internal::IsGarbageCollectedMixinType<T>::value ||
|
||||
sizeof(T) <= internal::api_constants::kLargeObjectSizeThreshold,
|
||||
"GarbageCollectedMixin may not be a large object");
|
||||
void* memory = MakeGarbageCollectedTraitBase<T>::Allocate(heap, sizeof(T));
|
||||
void* memory =
|
||||
MakeGarbageCollectedTraitBase<T>::Allocate(handle, sizeof(T));
|
||||
T* object = ::new (memory) T(std::forward<Args>(args)...);
|
||||
MakeGarbageCollectedTraitBase<T>::MarkObjectAsFullyConstructed(object);
|
||||
return object;
|
||||
@ -149,9 +169,10 @@ struct PostConstructionCallbackTrait {
|
||||
* \returns an instance of type T.
|
||||
*/
|
||||
template <typename T, typename... Args>
|
||||
T* MakeGarbageCollected(Heap* heap, Args&&... args) {
|
||||
T* MakeGarbageCollected(AllocationHandle& handle, // NOLINT(runtime/references)
|
||||
Args&&... args) {
|
||||
T* object =
|
||||
MakeGarbageCollectedTrait<T>::Call(heap, std::forward<Args>(args)...);
|
||||
MakeGarbageCollectedTrait<T>::Call(handle, std::forward<Args>(args)...);
|
||||
PostConstructionCallbackTrait<T>::Call(object);
|
||||
return object;
|
||||
}
|
||||
|
@ -18,6 +18,8 @@
|
||||
*/
|
||||
namespace cppgc {
|
||||
|
||||
class AllocationHandle;
|
||||
|
||||
namespace internal {
|
||||
class Heap;
|
||||
} // namespace internal
|
||||
@ -119,6 +121,8 @@ class V8_EXPORT Heap {
|
||||
const char* source, const char* reason,
|
||||
StackState stack_state = StackState::kMayContainHeapPointers);
|
||||
|
||||
AllocationHandle& GetAllocationHandle();
|
||||
|
||||
private:
|
||||
Heap() = default;
|
||||
|
||||
|
@ -94,8 +94,8 @@ int main(int argc, char* argv[]) {
|
||||
std::unique_ptr<cppgc::Heap> heap = cppgc::Heap::Create(cppgc_platform);
|
||||
// Allocate a string rope on the managed heap.
|
||||
auto* greeting = cppgc::MakeGarbageCollected<Rope>(
|
||||
heap.get(), "Hello ",
|
||||
cppgc::MakeGarbageCollected<Rope>(heap.get(), "World!"));
|
||||
heap->GetAllocationHandle(), "Hello ",
|
||||
cppgc::MakeGarbageCollected<Rope>(heap->GetAllocationHandle(), "World!"));
|
||||
// Manually trigger garbage collection. The object greeting is held alive
|
||||
// through conservative stack scanning.
|
||||
heap->ForceGarbageCollectionSlow("V8 embedders example", "Testing");
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
#include "src/base/logging.h"
|
||||
#include "src/base/macros.h"
|
||||
#include "src/heap/cppgc/heap-inl.h"
|
||||
#include "src/heap/cppgc/object-allocator-inl.h"
|
||||
|
||||
namespace cppgc {
|
||||
namespace internal {
|
||||
@ -15,19 +15,17 @@ STATIC_ASSERT(api_constants::kLargeObjectSizeThreshold ==
|
||||
kLargeObjectSizeThreshold);
|
||||
|
||||
// static
|
||||
void* MakeGarbageCollectedTraitInternal::Allocate(cppgc::Heap* heap,
|
||||
size_t size,
|
||||
GCInfoIndex index) {
|
||||
DCHECK_NOT_NULL(heap);
|
||||
return Heap::From(heap)->Allocate(size, index);
|
||||
void* MakeGarbageCollectedTraitInternal::Allocate(
|
||||
cppgc::AllocationHandle& handle, size_t size, GCInfoIndex index) {
|
||||
return static_cast<ObjectAllocator&>(handle).AllocateObject(size, index);
|
||||
}
|
||||
|
||||
// static
|
||||
void* MakeGarbageCollectedTraitInternal::Allocate(
|
||||
cppgc::Heap* heap, size_t size, GCInfoIndex index,
|
||||
cppgc::AllocationHandle& handle, size_t size, GCInfoIndex index,
|
||||
CustomSpaceIndex space_index) {
|
||||
DCHECK_NOT_NULL(heap);
|
||||
return Heap::From(heap)->Allocate(size, index, space_index);
|
||||
return static_cast<ObjectAllocator&>(handle).AllocateObject(size, index,
|
||||
space_index);
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
@ -1,29 +0,0 @@
|
||||
// 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.
|
||||
|
||||
#ifndef V8_HEAP_CPPGC_HEAP_INL_H_
|
||||
#define V8_HEAP_CPPGC_HEAP_INL_H_
|
||||
|
||||
#include "src/heap/cppgc/globals.h"
|
||||
#include "src/heap/cppgc/heap.h"
|
||||
#include "src/heap/cppgc/object-allocator-inl.h"
|
||||
|
||||
namespace cppgc {
|
||||
namespace internal {
|
||||
|
||||
void* Heap::Allocate(size_t size, GCInfoIndex index) {
|
||||
DCHECK(is_allocation_allowed());
|
||||
return object_allocator_.AllocateObject(size, index);
|
||||
}
|
||||
|
||||
void* Heap::Allocate(size_t size, GCInfoIndex index,
|
||||
CustomSpaceIndex space_index) {
|
||||
DCHECK(is_allocation_allowed());
|
||||
return object_allocator_.AllocateObject(size, index, space_index);
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace cppgc
|
||||
|
||||
#endif // V8_HEAP_CPPGC_HEAP_INL_H_
|
@ -50,6 +50,10 @@ void Heap::ForceGarbageCollectionSlow(const char* source, const char* reason,
|
||||
internal::Heap::From(this)->CollectGarbage({stack_state});
|
||||
}
|
||||
|
||||
AllocationHandle& Heap::GetAllocationHandle() {
|
||||
return internal::Heap::From(this)->GetObjectAllocator();
|
||||
}
|
||||
|
||||
namespace internal {
|
||||
|
||||
namespace {
|
||||
@ -166,7 +170,7 @@ void Heap::CollectGarbage(Config config) {
|
||||
// "Sweeping and finalization".
|
||||
{
|
||||
// Pre finalizers are forbidden from allocating objects
|
||||
NoAllocationScope no_allocation_scope_(this);
|
||||
ObjectAllocator::NoAllocationScope no_allocation_scope_(object_allocator_);
|
||||
marker_->ProcessWeakness();
|
||||
prefinalizer_handler_->InvokePreFinalizers();
|
||||
}
|
||||
@ -185,10 +189,5 @@ Heap::NoGCScope::NoGCScope(Heap* heap) : heap_(heap) { heap_->no_gc_scope_++; }
|
||||
|
||||
Heap::NoGCScope::~NoGCScope() { heap_->no_gc_scope_--; }
|
||||
|
||||
Heap::NoAllocationScope::NoAllocationScope(Heap* heap) : heap_(heap) {
|
||||
heap_->no_allocation_scope_++;
|
||||
}
|
||||
Heap::NoAllocationScope::~NoAllocationScope() { heap_->no_allocation_scope_--; }
|
||||
|
||||
} // namespace internal
|
||||
} // namespace cppgc
|
||||
|
@ -68,32 +68,15 @@ class V8_EXPORT_PRIVATE Heap final : public cppgc::Heap,
|
||||
Heap* const heap_;
|
||||
};
|
||||
|
||||
// NoAllocationScope is used in debug mode to catch unwanted allocations. E.g.
|
||||
// allocations during GC.
|
||||
class V8_EXPORT_PRIVATE NoAllocationScope final {
|
||||
CPPGC_STACK_ALLOCATED();
|
||||
|
||||
public:
|
||||
explicit NoAllocationScope(Heap* heap);
|
||||
~NoAllocationScope();
|
||||
|
||||
NoAllocationScope(const NoAllocationScope&) = delete;
|
||||
NoAllocationScope& operator=(const NoAllocationScope&) = delete;
|
||||
|
||||
private:
|
||||
Heap* const heap_;
|
||||
};
|
||||
|
||||
static Heap* From(cppgc::Heap* heap) { return static_cast<Heap*>(heap); }
|
||||
static const Heap* From(const cppgc::Heap* heap) {
|
||||
return static_cast<const Heap*>(heap);
|
||||
}
|
||||
|
||||
Heap(std::shared_ptr<cppgc::Platform> platform,
|
||||
cppgc::Heap::HeapOptions options);
|
||||
~Heap() final;
|
||||
|
||||
inline void* Allocate(size_t size, GCInfoIndex index);
|
||||
inline void* Allocate(size_t size, GCInfoIndex index,
|
||||
CustomSpaceIndex space_index);
|
||||
|
||||
void CollectGarbage(Config config) final;
|
||||
|
||||
PreFinalizerHandler* prefinalizer_handler() {
|
||||
@ -136,9 +119,10 @@ class V8_EXPORT_PRIVATE Heap final : public cppgc::Heap,
|
||||
|
||||
size_t ObjectPayloadSize() const;
|
||||
|
||||
ObjectAllocator& GetObjectAllocator() { return object_allocator_; }
|
||||
|
||||
private:
|
||||
bool in_no_gc_scope() const { return no_gc_scope_ > 0; }
|
||||
bool is_allocation_allowed() const { return no_allocation_scope_ == 0; }
|
||||
|
||||
RawHeap raw_heap_;
|
||||
|
||||
@ -166,7 +150,6 @@ class V8_EXPORT_PRIVATE Heap final : public cppgc::Heap,
|
||||
size_t epoch_ = 0;
|
||||
|
||||
size_t no_gc_scope_ = 0;
|
||||
size_t no_allocation_scope_ = 0;
|
||||
|
||||
friend class WriteBarrier;
|
||||
friend class testing::TestWithHeap;
|
||||
|
@ -20,6 +20,7 @@ namespace cppgc {
|
||||
namespace internal {
|
||||
|
||||
void* ObjectAllocator::AllocateObject(size_t size, GCInfoIndex gcinfo) {
|
||||
DCHECK(is_allocation_allowed());
|
||||
const size_t allocation_size =
|
||||
RoundUp<kAllocationGranularity>(size + sizeof(HeapObjectHeader));
|
||||
const RawHeap::RegularSpaceType type =
|
||||
@ -30,6 +31,7 @@ void* ObjectAllocator::AllocateObject(size_t size, GCInfoIndex gcinfo) {
|
||||
|
||||
void* ObjectAllocator::AllocateObject(size_t size, GCInfoIndex gcinfo,
|
||||
CustomSpaceIndex space_index) {
|
||||
DCHECK(is_allocation_allowed());
|
||||
const size_t allocation_size =
|
||||
RoundUp<kAllocationGranularity>(size + sizeof(HeapObjectHeader));
|
||||
return AllocateObjectOnSpace(
|
||||
|
@ -149,5 +149,15 @@ void ObjectAllocator::ResetLinearAllocationBuffers() {
|
||||
visitor.Traverse(raw_heap_);
|
||||
}
|
||||
|
||||
ObjectAllocator::NoAllocationScope::NoAllocationScope(
|
||||
ObjectAllocator& allocator)
|
||||
: allocator_(allocator) {
|
||||
allocator.no_allocation_scope_++;
|
||||
}
|
||||
|
||||
ObjectAllocator::NoAllocationScope::~NoAllocationScope() {
|
||||
allocator_.no_allocation_scope_--;
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace cppgc
|
||||
|
@ -5,18 +5,43 @@
|
||||
#ifndef V8_HEAP_CPPGC_OBJECT_ALLOCATOR_H_
|
||||
#define V8_HEAP_CPPGC_OBJECT_ALLOCATOR_H_
|
||||
|
||||
#include "include/cppgc/allocation.h"
|
||||
#include "include/cppgc/internal/gc-info.h"
|
||||
#include "include/cppgc/macros.h"
|
||||
#include "src/heap/cppgc/heap-space.h"
|
||||
#include "src/heap/cppgc/raw-heap.h"
|
||||
|
||||
namespace cppgc {
|
||||
|
||||
class V8_EXPORT AllocationHandle {
|
||||
private:
|
||||
AllocationHandle() = default;
|
||||
friend class internal::ObjectAllocator;
|
||||
};
|
||||
|
||||
namespace internal {
|
||||
|
||||
class StatsCollector;
|
||||
class PageBackend;
|
||||
|
||||
class V8_EXPORT_PRIVATE ObjectAllocator final {
|
||||
class V8_EXPORT_PRIVATE ObjectAllocator final : public cppgc::AllocationHandle {
|
||||
public:
|
||||
// NoAllocationScope is used in debug mode to catch unwanted allocations. E.g.
|
||||
// allocations during GC.
|
||||
class V8_EXPORT_PRIVATE NoAllocationScope final {
|
||||
CPPGC_STACK_ALLOCATED();
|
||||
|
||||
public:
|
||||
explicit NoAllocationScope(ObjectAllocator&);
|
||||
~NoAllocationScope();
|
||||
|
||||
NoAllocationScope(const NoAllocationScope&) = delete;
|
||||
NoAllocationScope& operator=(const NoAllocationScope&) = delete;
|
||||
|
||||
private:
|
||||
ObjectAllocator& allocator_;
|
||||
};
|
||||
|
||||
ObjectAllocator(RawHeap* heap, PageBackend* page_backend,
|
||||
StatsCollector* stats_collector);
|
||||
|
||||
@ -32,6 +57,8 @@ class V8_EXPORT_PRIVATE ObjectAllocator final {
|
||||
inline static RawHeap::RegularSpaceType GetInitialSpaceIndexForSize(
|
||||
size_t size);
|
||||
|
||||
bool is_allocation_allowed() const { return no_allocation_scope_ == 0; }
|
||||
|
||||
inline void* AllocateObjectOnSpace(NormalPageSpace* space, size_t size,
|
||||
GCInfoIndex gcinfo);
|
||||
void* OutOfLineAllocate(NormalPageSpace*, size_t, GCInfoIndex);
|
||||
@ -41,6 +68,7 @@ class V8_EXPORT_PRIVATE ObjectAllocator final {
|
||||
RawHeap* raw_heap_;
|
||||
PageBackend* page_backend_;
|
||||
StatsCollector* stats_collector_;
|
||||
size_t no_allocation_scope_ = 0;
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
@ -132,8 +132,8 @@ TEST_F(ConcurrentSweeperTest, BackgroundSweepOfNormalPage) {
|
||||
// Non finalizable objects are swept right away.
|
||||
using GCedType = NormalNonFinalizable;
|
||||
|
||||
auto* unmarked_object = MakeGarbageCollected<GCedType>(GetHeap());
|
||||
auto* marked_object = MakeGarbageCollected<GCedType>(GetHeap());
|
||||
auto* unmarked_object = MakeGarbageCollected<GCedType>(GetAllocationHandle());
|
||||
auto* marked_object = MakeGarbageCollected<GCedType>(GetAllocationHandle());
|
||||
HeapObjectHeader::FromPayload(marked_object).TryMarkAtomic();
|
||||
|
||||
auto* page = BasePage::FromPayload(unmarked_object);
|
||||
@ -166,8 +166,8 @@ TEST_F(ConcurrentSweeperTest, BackgroundSweepOfLargePage) {
|
||||
// Non finalizable objects are swept right away.
|
||||
using GCedType = LargeNonFinalizable;
|
||||
|
||||
auto* unmarked_object = MakeGarbageCollected<GCedType>(GetHeap());
|
||||
auto* marked_object = MakeGarbageCollected<GCedType>(GetHeap());
|
||||
auto* unmarked_object = MakeGarbageCollected<GCedType>(GetAllocationHandle());
|
||||
auto* marked_object = MakeGarbageCollected<GCedType>(GetAllocationHandle());
|
||||
HeapObjectHeader::FromPayload(marked_object).TryMarkAtomic();
|
||||
|
||||
auto* unmarked_page = BasePage::FromPayload(unmarked_object);
|
||||
@ -204,7 +204,7 @@ TEST_F(ConcurrentSweeperTest, DeferredFinalizationOfNormalPage) {
|
||||
|
||||
BaseSpace* space = nullptr;
|
||||
for (size_t i = 0; i < kNumberOfObjects; ++i) {
|
||||
auto* object = MakeGarbageCollected<GCedType>(GetHeap());
|
||||
auto* object = MakeGarbageCollected<GCedType>(GetAllocationHandle());
|
||||
objects.push_back(object);
|
||||
auto* page = BasePage::FromPayload(object);
|
||||
pages.insert(page);
|
||||
@ -238,7 +238,7 @@ TEST_F(ConcurrentSweeperTest, DeferredFinalizationOfNormalPage) {
|
||||
TEST_F(ConcurrentSweeperTest, DeferredFinalizationOfLargePage) {
|
||||
using GCedType = LargeFinalizable;
|
||||
|
||||
auto* object = MakeGarbageCollected<GCedType>(GetHeap());
|
||||
auto* object = MakeGarbageCollected<GCedType>(GetAllocationHandle());
|
||||
|
||||
auto* page = BasePage::FromPayload(object);
|
||||
auto* space = page->space();
|
||||
@ -268,13 +268,14 @@ TEST_F(ConcurrentSweeperTest, IncrementalSweeping) {
|
||||
auto task_runner = GetPlatform().GetForegroundTaskRunner();
|
||||
|
||||
// Create two unmarked objects.
|
||||
MakeGarbageCollected<NormalFinalizable>(GetHeap());
|
||||
MakeGarbageCollected<LargeFinalizable>(GetHeap());
|
||||
MakeGarbageCollected<NormalFinalizable>(GetAllocationHandle());
|
||||
MakeGarbageCollected<LargeFinalizable>(GetAllocationHandle());
|
||||
|
||||
// Create two marked objects.
|
||||
auto* marked_normal_object =
|
||||
MakeGarbageCollected<NormalFinalizable>(GetHeap());
|
||||
auto* marked_large_object = MakeGarbageCollected<LargeFinalizable>(GetHeap());
|
||||
MakeGarbageCollected<NormalFinalizable>(GetAllocationHandle());
|
||||
auto* marked_large_object =
|
||||
MakeGarbageCollected<LargeFinalizable>(GetAllocationHandle());
|
||||
|
||||
auto& marked_normal_header =
|
||||
HeapObjectHeader::FromPayload(marked_normal_object);
|
||||
|
@ -99,9 +99,12 @@ struct SpaceTrait<
|
||||
namespace internal {
|
||||
|
||||
TEST_F(TestWithHeapWithCustomSpaces, AllocateOnCustomSpaces) {
|
||||
auto* regular = MakeGarbageCollected<RegularGCed>(GetHeap());
|
||||
auto* custom1 = MakeGarbageCollected<CustomGCed1>(GetHeap());
|
||||
auto* custom2 = MakeGarbageCollected<CustomGCed2>(GetHeap());
|
||||
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,
|
||||
@ -112,9 +115,12 @@ TEST_F(TestWithHeapWithCustomSpaces, AllocateOnCustomSpaces) {
|
||||
|
||||
TEST_F(TestWithHeapWithCustomSpaces,
|
||||
AllocateOnCustomSpacesSpecifiedThroughBase) {
|
||||
auto* regular = MakeGarbageCollected<RegularGCed>(GetHeap());
|
||||
auto* custom1 = MakeGarbageCollected<CustomGCedFinal1>(GetHeap());
|
||||
auto* custom2 = MakeGarbageCollected<CustomGCedFinal2>(GetHeap());
|
||||
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,
|
||||
@ -124,10 +130,10 @@ TEST_F(TestWithHeapWithCustomSpaces,
|
||||
}
|
||||
|
||||
TEST_F(TestWithHeapWithCustomSpaces, SweepCustomSpace) {
|
||||
MakeGarbageCollected<CustomGCedFinal1>(GetHeap());
|
||||
MakeGarbageCollected<CustomGCedFinal2>(GetHeap());
|
||||
MakeGarbageCollected<CustomGCed1>(GetHeap());
|
||||
MakeGarbageCollected<CustomGCed2>(GetHeap());
|
||||
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);
|
||||
|
@ -70,9 +70,9 @@ TEST(GarbageCollectedTest, GarbageCollectedMixinTrait) {
|
||||
}
|
||||
|
||||
TEST_F(GarbageCollectedTestWithHeap, GetObjectStartReturnsCurrentAddress) {
|
||||
GCed* gced = MakeGarbageCollected<GCed>(GetHeap());
|
||||
GCed* gced = MakeGarbageCollected<GCed>(GetAllocationHandle());
|
||||
GCedWithMixin* gced_with_mixin =
|
||||
MakeGarbageCollected<GCedWithMixin>(GetHeap());
|
||||
MakeGarbageCollected<GCedWithMixin>(GetAllocationHandle());
|
||||
EXPECT_EQ(gced_with_mixin, static_cast<Mixin*>(gced_with_mixin)
|
||||
->GetTraceDescriptor()
|
||||
.base_object_payload);
|
||||
@ -132,13 +132,14 @@ namespace internal {
|
||||
|
||||
TEST_F(GarbageCollectedTestWithHeap, PostConstructionCallback) {
|
||||
EXPECT_EQ(0u, GCedWithPostConstructionCallback::cb_callcount);
|
||||
MakeGarbageCollected<GCedWithPostConstructionCallback>(GetHeap());
|
||||
MakeGarbageCollected<GCedWithPostConstructionCallback>(GetAllocationHandle());
|
||||
EXPECT_EQ(1u, GCedWithPostConstructionCallback::cb_callcount);
|
||||
}
|
||||
|
||||
TEST_F(GarbageCollectedTestWithHeap, PostConstructionCallbackForMixin) {
|
||||
EXPECT_EQ(0u, MixinWithPostConstructionCallback::cb_callcount);
|
||||
MakeGarbageCollected<GCedWithMixinWithPostConstructionCallback>(GetHeap());
|
||||
MakeGarbageCollected<GCedWithMixinWithPostConstructionCallback>(
|
||||
GetAllocationHandle());
|
||||
EXPECT_EQ(1u, MixinWithPostConstructionCallback::cb_callcount);
|
||||
}
|
||||
|
||||
|
@ -42,7 +42,7 @@ class GCed : public GarbageCollected<GCed<Size>> {
|
||||
} // namespace
|
||||
|
||||
TEST_F(PageTest, GetHeapForAllocatedObject) {
|
||||
auto* gced = MakeGarbageCollected<GCed<1>>(GetHeap());
|
||||
auto* gced = MakeGarbageCollected<GCed<1>>(GetAllocationHandle());
|
||||
EXPECT_EQ(GetHeap(), GetHeapFromPayload(gced));
|
||||
}
|
||||
|
||||
@ -61,36 +61,36 @@ TEST_F(PageTest, PredefinedSpaces) {
|
||||
using SpaceType = RawHeap::RegularSpaceType;
|
||||
RawHeap& heap = GetRawHeap();
|
||||
{
|
||||
auto* gced = MakeGarbageCollected<GCed<1>>(GetHeap());
|
||||
auto* gced = MakeGarbageCollected<GCed<1>>(GetAllocationHandle());
|
||||
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());
|
||||
auto* gced = MakeGarbageCollected<GCed<32>>(GetAllocationHandle());
|
||||
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());
|
||||
auto* gced = MakeGarbageCollected<GCed<64>>(GetAllocationHandle());
|
||||
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());
|
||||
auto* gced = MakeGarbageCollected<GCed<128>>(GetAllocationHandle());
|
||||
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());
|
||||
auto* gced = MakeGarbageCollected<GCed<2 * kLargeObjectSizeThreshold>>(
|
||||
GetAllocationHandle());
|
||||
BaseSpace* space = NormalPage::FromPayload(gced)->space();
|
||||
EXPECT_EQ(heap.Space(SpaceType::kLarge), space);
|
||||
EXPECT_EQ(4u, space->index());
|
||||
@ -110,7 +110,7 @@ TEST_F(PageTest, NormalPageIndexing) {
|
||||
|
||||
std::vector<Persistent<Type>> persistents(kNumberOfObjects);
|
||||
for (auto& p : persistents) {
|
||||
p = MakeGarbageCollected<Type>(GetHeap());
|
||||
p = MakeGarbageCollected<Type>(GetAllocationHandle());
|
||||
}
|
||||
|
||||
const RawHeap& heap = GetRawHeap();
|
||||
@ -135,7 +135,7 @@ TEST_F(PageTest, LargePageIndexing) {
|
||||
|
||||
std::vector<Persistent<Type>> persistents(kNumberOfObjects);
|
||||
for (auto& p : persistents) {
|
||||
p = MakeGarbageCollected<Type>(GetHeap());
|
||||
p = MakeGarbageCollected<Type>(GetAllocationHandle());
|
||||
}
|
||||
|
||||
const RawHeap& heap = GetRawHeap();
|
||||
@ -160,7 +160,7 @@ TEST_F(PageTest, HeapObjectHeaderOnBasePageIndexing) {
|
||||
|
||||
std::vector<Persistent<Type>> persistents(kNumberOfObjects);
|
||||
for (auto& p : persistents) {
|
||||
p = MakeGarbageCollected<Type>(GetHeap());
|
||||
p = MakeGarbageCollected<Type>(GetAllocationHandle());
|
||||
}
|
||||
|
||||
const auto* page =
|
||||
@ -180,7 +180,7 @@ TEST_F(PageTest, HeapObjectHeaderOnBasePageIndexing) {
|
||||
TEST_F(PageTest, HeapObjectHeaderOnLargePageIndexing) {
|
||||
constexpr size_t kObjectSize = 2 * kLargeObjectSizeThreshold;
|
||||
using Type = GCed<kObjectSize>;
|
||||
auto* gced = MakeGarbageCollected<Type>(GetHeap());
|
||||
auto* gced = MakeGarbageCollected<Type>(GetAllocationHandle());
|
||||
|
||||
const auto* page = static_cast<LargePage*>(BasePage::FromPayload(gced));
|
||||
const size_t expected_payload_size =
|
||||
@ -260,7 +260,7 @@ TEST_F(PageTest, UnsweptPageDestruction) {
|
||||
|
||||
TEST_F(PageTest, ObjectHeaderFromInnerAddress) {
|
||||
{
|
||||
auto* object = MakeGarbageCollected<GCed<64>>(GetHeap());
|
||||
auto* object = MakeGarbageCollected<GCed<64>>(GetAllocationHandle());
|
||||
const HeapObjectHeader& expected = HeapObjectHeader::FromPayload(object);
|
||||
|
||||
for (auto* inner_ptr = reinterpret_cast<ConstAddress>(object);
|
||||
@ -272,8 +272,8 @@ TEST_F(PageTest, ObjectHeaderFromInnerAddress) {
|
||||
}
|
||||
}
|
||||
{
|
||||
auto* object =
|
||||
MakeGarbageCollected<GCed<2 * kLargeObjectSizeThreshold>>(GetHeap());
|
||||
auto* object = MakeGarbageCollected<GCed<2 * kLargeObjectSizeThreshold>>(
|
||||
GetAllocationHandle());
|
||||
const HeapObjectHeader& expected = HeapObjectHeader::FromPayload(object);
|
||||
|
||||
const HeapObjectHeader& hoh =
|
||||
|
@ -52,7 +52,8 @@ class GCed : public GarbageCollected<Foo> {
|
||||
} // namespace
|
||||
|
||||
TEST_F(GCHeapTest, PreciseGCReclaimsObjectOnStack) {
|
||||
Foo* volatile do_not_access = MakeGarbageCollected<Foo>(GetHeap());
|
||||
Foo* volatile do_not_access =
|
||||
MakeGarbageCollected<Foo>(GetAllocationHandle());
|
||||
USE(do_not_access);
|
||||
EXPECT_EQ(0u, Foo::destructor_callcount);
|
||||
PreciseGC();
|
||||
@ -73,7 +74,7 @@ const void* ConservativeGCReturningObject(cppgc::Heap* heap,
|
||||
} // namespace
|
||||
|
||||
TEST_F(GCHeapTest, ConservativeGCRetainsObjectOnStack) {
|
||||
Foo* volatile object = MakeGarbageCollected<Foo>(GetHeap());
|
||||
Foo* volatile object = MakeGarbageCollected<Foo>(GetAllocationHandle());
|
||||
EXPECT_EQ(0u, Foo::destructor_callcount);
|
||||
EXPECT_EQ(object, ConservativeGCReturningObject(GetHeap(), object));
|
||||
EXPECT_EQ(0u, Foo::destructor_callcount);
|
||||
@ -94,11 +95,11 @@ TEST_F(GCHeapTest, ObjectPayloadSize) {
|
||||
Heap::NoGCScope no_gc_scope(Heap::From(GetHeap()));
|
||||
|
||||
for (size_t k = 0; k < kNumberOfObjectsPerArena; ++k) {
|
||||
MakeGarbageCollected<GCed<kObjectSizes[0]>>(GetHeap());
|
||||
MakeGarbageCollected<GCed<kObjectSizes[1]>>(GetHeap());
|
||||
MakeGarbageCollected<GCed<kObjectSizes[2]>>(GetHeap());
|
||||
MakeGarbageCollected<GCed<kObjectSizes[3]>>(GetHeap());
|
||||
MakeGarbageCollected<GCed<kObjectSizes[4]>>(GetHeap());
|
||||
MakeGarbageCollected<GCed<kObjectSizes[0]>>(GetAllocationHandle());
|
||||
MakeGarbageCollected<GCed<kObjectSizes[1]>>(GetAllocationHandle());
|
||||
MakeGarbageCollected<GCed<kObjectSizes[2]>>(GetAllocationHandle());
|
||||
MakeGarbageCollected<GCed<kObjectSizes[3]>>(GetAllocationHandle());
|
||||
MakeGarbageCollected<GCed<kObjectSizes[4]>>(GetAllocationHandle());
|
||||
}
|
||||
|
||||
size_t aligned_object_sizes[arraysize(kObjectSizes)];
|
||||
|
@ -58,7 +58,7 @@ V8_NOINLINE T access(volatile const T& t) {
|
||||
} // namespace
|
||||
|
||||
TEST_F(MarkerTest, PersistentIsMarked) {
|
||||
Persistent<GCed> object = MakeGarbageCollected<GCed>(GetHeap());
|
||||
Persistent<GCed> object = MakeGarbageCollected<GCed>(GetAllocationHandle());
|
||||
HeapObjectHeader& header = HeapObjectHeader::FromPayload(object);
|
||||
EXPECT_FALSE(header.IsMarked());
|
||||
DoMarking({MarkingConfig::StackState::kNoHeapPointers});
|
||||
@ -66,8 +66,8 @@ TEST_F(MarkerTest, PersistentIsMarked) {
|
||||
}
|
||||
|
||||
TEST_F(MarkerTest, ReachableMemberIsMarked) {
|
||||
Persistent<GCed> parent = MakeGarbageCollected<GCed>(GetHeap());
|
||||
parent->SetChild(MakeGarbageCollected<GCed>(GetHeap()));
|
||||
Persistent<GCed> parent = MakeGarbageCollected<GCed>(GetAllocationHandle());
|
||||
parent->SetChild(MakeGarbageCollected<GCed>(GetAllocationHandle()));
|
||||
HeapObjectHeader& header = HeapObjectHeader::FromPayload(parent->child());
|
||||
EXPECT_FALSE(header.IsMarked());
|
||||
DoMarking({MarkingConfig::StackState::kNoHeapPointers});
|
||||
@ -75,7 +75,7 @@ TEST_F(MarkerTest, ReachableMemberIsMarked) {
|
||||
}
|
||||
|
||||
TEST_F(MarkerTest, UnreachableMemberIsNotMarked) {
|
||||
Member<GCed> object = MakeGarbageCollected<GCed>(GetHeap());
|
||||
Member<GCed> object = MakeGarbageCollected<GCed>(GetAllocationHandle());
|
||||
HeapObjectHeader& header = HeapObjectHeader::FromPayload(object);
|
||||
EXPECT_FALSE(header.IsMarked());
|
||||
DoMarking({MarkingConfig::StackState::kNoHeapPointers});
|
||||
@ -83,7 +83,7 @@ TEST_F(MarkerTest, UnreachableMemberIsNotMarked) {
|
||||
}
|
||||
|
||||
TEST_F(MarkerTest, ObjectReachableFromStackIsMarked) {
|
||||
GCed* object = MakeGarbageCollected<GCed>(GetHeap());
|
||||
GCed* object = MakeGarbageCollected<GCed>(GetAllocationHandle());
|
||||
EXPECT_FALSE(HeapObjectHeader::FromPayload(object).IsMarked());
|
||||
DoMarking({MarkingConfig::StackState::kMayContainHeapPointers});
|
||||
EXPECT_TRUE(HeapObjectHeader::FromPayload(object).IsMarked());
|
||||
@ -91,7 +91,7 @@ TEST_F(MarkerTest, ObjectReachableFromStackIsMarked) {
|
||||
}
|
||||
|
||||
TEST_F(MarkerTest, ObjectReachableOnlyFromStackIsNotMarkedIfStackIsEmpty) {
|
||||
GCed* object = MakeGarbageCollected<GCed>(GetHeap());
|
||||
GCed* object = MakeGarbageCollected<GCed>(GetAllocationHandle());
|
||||
HeapObjectHeader& header = HeapObjectHeader::FromPayload(object);
|
||||
EXPECT_FALSE(header.IsMarked());
|
||||
DoMarking({MarkingConfig::StackState::kNoHeapPointers});
|
||||
@ -101,14 +101,15 @@ TEST_F(MarkerTest, ObjectReachableOnlyFromStackIsNotMarkedIfStackIsEmpty) {
|
||||
|
||||
TEST_F(MarkerTest, WeakReferenceToUnreachableObjectIsCleared) {
|
||||
{
|
||||
WeakPersistent<GCed> weak_object = MakeGarbageCollected<GCed>(GetHeap());
|
||||
WeakPersistent<GCed> weak_object =
|
||||
MakeGarbageCollected<GCed>(GetAllocationHandle());
|
||||
EXPECT_TRUE(weak_object);
|
||||
DoMarking({MarkingConfig::StackState::kNoHeapPointers});
|
||||
EXPECT_FALSE(weak_object);
|
||||
}
|
||||
{
|
||||
Persistent<GCed> parent = MakeGarbageCollected<GCed>(GetHeap());
|
||||
parent->SetWeakChild(MakeGarbageCollected<GCed>(GetHeap()));
|
||||
Persistent<GCed> parent = MakeGarbageCollected<GCed>(GetAllocationHandle());
|
||||
parent->SetWeakChild(MakeGarbageCollected<GCed>(GetAllocationHandle()));
|
||||
EXPECT_TRUE(parent->weak_child());
|
||||
DoMarking({MarkingConfig::StackState::kNoHeapPointers});
|
||||
EXPECT_FALSE(parent->weak_child());
|
||||
@ -118,15 +119,15 @@ TEST_F(MarkerTest, WeakReferenceToUnreachableObjectIsCleared) {
|
||||
TEST_F(MarkerTest, WeakReferenceToReachableObjectIsNotCleared) {
|
||||
// Reachable from Persistent
|
||||
{
|
||||
Persistent<GCed> object = MakeGarbageCollected<GCed>(GetHeap());
|
||||
Persistent<GCed> object = MakeGarbageCollected<GCed>(GetAllocationHandle());
|
||||
WeakPersistent<GCed> weak_object(object);
|
||||
EXPECT_TRUE(weak_object);
|
||||
DoMarking({MarkingConfig::StackState::kNoHeapPointers});
|
||||
EXPECT_TRUE(weak_object);
|
||||
}
|
||||
{
|
||||
Persistent<GCed> object = MakeGarbageCollected<GCed>(GetHeap());
|
||||
Persistent<GCed> parent = MakeGarbageCollected<GCed>(GetHeap());
|
||||
Persistent<GCed> object = MakeGarbageCollected<GCed>(GetAllocationHandle());
|
||||
Persistent<GCed> parent = MakeGarbageCollected<GCed>(GetAllocationHandle());
|
||||
parent->SetWeakChild(object);
|
||||
EXPECT_TRUE(parent->weak_child());
|
||||
DoMarking({MarkingConfig::StackState::kNoHeapPointers});
|
||||
@ -134,16 +135,17 @@ TEST_F(MarkerTest, WeakReferenceToReachableObjectIsNotCleared) {
|
||||
}
|
||||
// Reachable from Member
|
||||
{
|
||||
Persistent<GCed> parent = MakeGarbageCollected<GCed>(GetHeap());
|
||||
WeakPersistent<GCed> weak_object(MakeGarbageCollected<GCed>(GetHeap()));
|
||||
Persistent<GCed> parent = MakeGarbageCollected<GCed>(GetAllocationHandle());
|
||||
WeakPersistent<GCed> weak_object(
|
||||
MakeGarbageCollected<GCed>(GetAllocationHandle()));
|
||||
parent->SetChild(weak_object);
|
||||
EXPECT_TRUE(weak_object);
|
||||
DoMarking({MarkingConfig::StackState::kNoHeapPointers});
|
||||
EXPECT_TRUE(weak_object);
|
||||
}
|
||||
{
|
||||
Persistent<GCed> parent = MakeGarbageCollected<GCed>(GetHeap());
|
||||
parent->SetChild(MakeGarbageCollected<GCed>(GetHeap()));
|
||||
Persistent<GCed> parent = MakeGarbageCollected<GCed>(GetAllocationHandle());
|
||||
parent->SetChild(MakeGarbageCollected<GCed>(GetAllocationHandle()));
|
||||
parent->SetWeakChild(parent->child());
|
||||
EXPECT_TRUE(parent->weak_child());
|
||||
DoMarking({MarkingConfig::StackState::kNoHeapPointers});
|
||||
@ -151,7 +153,7 @@ TEST_F(MarkerTest, WeakReferenceToReachableObjectIsNotCleared) {
|
||||
}
|
||||
// Reachable from stack
|
||||
{
|
||||
GCed* object = MakeGarbageCollected<GCed>(GetHeap());
|
||||
GCed* object = MakeGarbageCollected<GCed>(GetAllocationHandle());
|
||||
WeakPersistent<GCed> weak_object(object);
|
||||
EXPECT_TRUE(weak_object);
|
||||
DoMarking({MarkingConfig::StackState::kMayContainHeapPointers});
|
||||
@ -159,8 +161,8 @@ TEST_F(MarkerTest, WeakReferenceToReachableObjectIsNotCleared) {
|
||||
access(object);
|
||||
}
|
||||
{
|
||||
GCed* object = MakeGarbageCollected<GCed>(GetHeap());
|
||||
Persistent<GCed> parent = MakeGarbageCollected<GCed>(GetHeap());
|
||||
GCed* object = MakeGarbageCollected<GCed>(GetAllocationHandle());
|
||||
Persistent<GCed> parent = MakeGarbageCollected<GCed>(GetAllocationHandle());
|
||||
parent->SetWeakChild(object);
|
||||
EXPECT_TRUE(parent->weak_child());
|
||||
DoMarking({MarkingConfig::StackState::kMayContainHeapPointers});
|
||||
@ -171,10 +173,10 @@ TEST_F(MarkerTest, WeakReferenceToReachableObjectIsNotCleared) {
|
||||
|
||||
TEST_F(MarkerTest, DeepHierarchyIsMarked) {
|
||||
static constexpr int kHierarchyDepth = 10;
|
||||
Persistent<GCed> root = MakeGarbageCollected<GCed>(GetHeap());
|
||||
Persistent<GCed> root = MakeGarbageCollected<GCed>(GetAllocationHandle());
|
||||
GCed* parent = root;
|
||||
for (int i = 0; i < kHierarchyDepth; ++i) {
|
||||
parent->SetChild(MakeGarbageCollected<GCed>(GetHeap()));
|
||||
parent->SetChild(MakeGarbageCollected<GCed>(GetAllocationHandle()));
|
||||
parent->SetWeakChild(parent->child());
|
||||
parent = parent->child();
|
||||
}
|
||||
@ -189,9 +191,9 @@ TEST_F(MarkerTest, DeepHierarchyIsMarked) {
|
||||
}
|
||||
|
||||
TEST_F(MarkerTest, NestedObjectsOnStackAreMarked) {
|
||||
GCed* root = MakeGarbageCollected<GCed>(GetHeap());
|
||||
root->SetChild(MakeGarbageCollected<GCed>(GetHeap()));
|
||||
root->child()->SetChild(MakeGarbageCollected<GCed>(GetHeap()));
|
||||
GCed* root = MakeGarbageCollected<GCed>(GetAllocationHandle());
|
||||
root->SetChild(MakeGarbageCollected<GCed>(GetAllocationHandle()));
|
||||
root->child()->SetChild(MakeGarbageCollected<GCed>(GetAllocationHandle()));
|
||||
DoMarking({MarkingConfig::StackState::kMayContainHeapPointers});
|
||||
EXPECT_TRUE(HeapObjectHeader::FromPayload(root).IsMarked());
|
||||
EXPECT_TRUE(HeapObjectHeader::FromPayload(root->child()).IsMarked());
|
||||
@ -214,7 +216,7 @@ TEST_F(MarkerTest, InConstructionObjectIsEventuallyMarkedEmptyStack) {
|
||||
Marker marker(Heap::From(GetHeap()));
|
||||
marker.StartMarking({MarkingConfig::StackState::kMayContainHeapPointers});
|
||||
GCedWithCallback* object = MakeGarbageCollected<GCedWithCallback>(
|
||||
GetHeap(), [&marker](GCedWithCallback* obj) {
|
||||
GetAllocationHandle(), [&marker](GCedWithCallback* obj) {
|
||||
Member<GCedWithCallback> member(obj);
|
||||
marker.GetMarkingVisitorForTesting()->Trace(member);
|
||||
});
|
||||
@ -226,14 +228,15 @@ TEST_F(MarkerTest, InConstructionObjectIsEventuallyMarkedEmptyStack) {
|
||||
TEST_F(MarkerTest, InConstructionObjectIsEventuallyMarkedNonEmptyStack) {
|
||||
Marker marker(Heap::From(GetHeap()));
|
||||
marker.StartMarking({MarkingConfig::StackState::kMayContainHeapPointers});
|
||||
MakeGarbageCollected<GCedWithCallback>(GetHeap(), [&marker](
|
||||
GCedWithCallback* obj) {
|
||||
Member<GCedWithCallback> member(obj);
|
||||
marker.GetMarkingVisitorForTesting()->Trace(member);
|
||||
EXPECT_FALSE(HeapObjectHeader::FromPayload(obj).IsMarked());
|
||||
marker.FinishMarking({MarkingConfig::StackState::kMayContainHeapPointers});
|
||||
EXPECT_TRUE(HeapObjectHeader::FromPayload(obj).IsMarked());
|
||||
});
|
||||
MakeGarbageCollected<GCedWithCallback>(
|
||||
GetAllocationHandle(), [&marker](GCedWithCallback* obj) {
|
||||
Member<GCedWithCallback> member(obj);
|
||||
marker.GetMarkingVisitorForTesting()->Trace(member);
|
||||
EXPECT_FALSE(HeapObjectHeader::FromPayload(obj).IsMarked());
|
||||
marker.FinishMarking(
|
||||
{MarkingConfig::StackState::kMayContainHeapPointers});
|
||||
EXPECT_TRUE(HeapObjectHeader::FromPayload(obj).IsMarked());
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
@ -54,7 +54,7 @@ TEST_F(MarkingVisitorTest, MarkedBytesAreInitiallyZero) {
|
||||
// Strong refernces are marked.
|
||||
|
||||
TEST_F(MarkingVisitorTest, MarkMember) {
|
||||
Member<GCed> object(MakeGarbageCollected<GCed>(GetHeap()));
|
||||
Member<GCed> object(MakeGarbageCollected<GCed>(GetAllocationHandle()));
|
||||
HeapObjectHeader& header = HeapObjectHeader::FromPayload(object);
|
||||
|
||||
MutatorThreadMarkingVisitor visitor(GetMarker());
|
||||
@ -67,7 +67,8 @@ TEST_F(MarkingVisitorTest, MarkMember) {
|
||||
}
|
||||
|
||||
TEST_F(MarkingVisitorTest, MarkMemberMixin) {
|
||||
GCedWithMixin* object(MakeGarbageCollected<GCedWithMixin>(GetHeap()));
|
||||
GCedWithMixin* object(
|
||||
MakeGarbageCollected<GCedWithMixin>(GetAllocationHandle()));
|
||||
Member<Mixin> mixin(object);
|
||||
HeapObjectHeader& header = HeapObjectHeader::FromPayload(object);
|
||||
|
||||
@ -81,7 +82,7 @@ TEST_F(MarkingVisitorTest, MarkMemberMixin) {
|
||||
}
|
||||
|
||||
TEST_F(MarkingVisitorTest, MarkPersistent) {
|
||||
Persistent<GCed> object(MakeGarbageCollected<GCed>(GetHeap()));
|
||||
Persistent<GCed> object(MakeGarbageCollected<GCed>(GetAllocationHandle()));
|
||||
HeapObjectHeader& header = HeapObjectHeader::FromPayload(object);
|
||||
|
||||
MutatorThreadMarkingVisitor visitor(GetMarker());
|
||||
@ -94,7 +95,8 @@ TEST_F(MarkingVisitorTest, MarkPersistent) {
|
||||
}
|
||||
|
||||
TEST_F(MarkingVisitorTest, MarkPersistentMixin) {
|
||||
GCedWithMixin* object(MakeGarbageCollected<GCedWithMixin>(GetHeap()));
|
||||
GCedWithMixin* object(
|
||||
MakeGarbageCollected<GCedWithMixin>(GetAllocationHandle()));
|
||||
Persistent<Mixin> mixin(object);
|
||||
HeapObjectHeader& header = HeapObjectHeader::FromPayload(object);
|
||||
|
||||
@ -110,7 +112,7 @@ TEST_F(MarkingVisitorTest, MarkPersistentMixin) {
|
||||
// Weak references are not marked.
|
||||
|
||||
TEST_F(MarkingVisitorTest, DontMarkWeakMember) {
|
||||
WeakMember<GCed> object(MakeGarbageCollected<GCed>(GetHeap()));
|
||||
WeakMember<GCed> object(MakeGarbageCollected<GCed>(GetAllocationHandle()));
|
||||
HeapObjectHeader& header = HeapObjectHeader::FromPayload(object);
|
||||
|
||||
MutatorThreadMarkingVisitor visitor(GetMarker());
|
||||
@ -123,7 +125,8 @@ TEST_F(MarkingVisitorTest, DontMarkWeakMember) {
|
||||
}
|
||||
|
||||
TEST_F(MarkingVisitorTest, DontMarkWeakMemberMixin) {
|
||||
GCedWithMixin* object(MakeGarbageCollected<GCedWithMixin>(GetHeap()));
|
||||
GCedWithMixin* object(
|
||||
MakeGarbageCollected<GCedWithMixin>(GetAllocationHandle()));
|
||||
WeakMember<Mixin> mixin(object);
|
||||
HeapObjectHeader& header = HeapObjectHeader::FromPayload(object);
|
||||
|
||||
@ -137,7 +140,8 @@ TEST_F(MarkingVisitorTest, DontMarkWeakMemberMixin) {
|
||||
}
|
||||
|
||||
TEST_F(MarkingVisitorTest, DontMarkWeakPersistent) {
|
||||
WeakPersistent<GCed> object(MakeGarbageCollected<GCed>(GetHeap()));
|
||||
WeakPersistent<GCed> object(
|
||||
MakeGarbageCollected<GCed>(GetAllocationHandle()));
|
||||
HeapObjectHeader& header = HeapObjectHeader::FromPayload(object);
|
||||
|
||||
MutatorThreadMarkingVisitor visitor(GetMarker());
|
||||
@ -150,7 +154,8 @@ TEST_F(MarkingVisitorTest, DontMarkWeakPersistent) {
|
||||
}
|
||||
|
||||
TEST_F(MarkingVisitorTest, DontMarkWeakPersistentMixin) {
|
||||
GCedWithMixin* object(MakeGarbageCollected<GCedWithMixin>(GetHeap()));
|
||||
GCedWithMixin* object(
|
||||
MakeGarbageCollected<GCedWithMixin>(GetAllocationHandle()));
|
||||
WeakPersistent<Mixin> mixin(object);
|
||||
HeapObjectHeader& header = HeapObjectHeader::FromPayload(object);
|
||||
|
||||
@ -202,7 +207,8 @@ TEST_F(MarkingVisitorTest, DontMarkMemberInConstruction) {
|
||||
MutatorThreadMarkingVisitor visitor(GetMarker());
|
||||
GCedWithInConstructionCallback* gced =
|
||||
MakeGarbageCollected<GCedWithInConstructionCallback>(
|
||||
GetHeap(), [&visitor](GCedWithInConstructionCallback* obj) {
|
||||
GetAllocationHandle(),
|
||||
[&visitor](GCedWithInConstructionCallback* obj) {
|
||||
Member<GCedWithInConstructionCallback> object(obj);
|
||||
visitor.Trace(object);
|
||||
});
|
||||
@ -213,7 +219,8 @@ TEST_F(MarkingVisitorTest, DontMarkMemberMixinInConstruction) {
|
||||
MutatorThreadMarkingVisitor visitor(GetMarker());
|
||||
GCedWithMixinWithInConstructionCallback* gced =
|
||||
MakeGarbageCollected<GCedWithMixinWithInConstructionCallback>(
|
||||
GetHeap(), [&visitor](MixinWithInConstructionCallback* obj) {
|
||||
GetAllocationHandle(),
|
||||
[&visitor](MixinWithInConstructionCallback* obj) {
|
||||
Member<MixinWithInConstructionCallback> mixin(obj);
|
||||
visitor.Trace(mixin);
|
||||
});
|
||||
@ -224,7 +231,8 @@ TEST_F(MarkingVisitorTest, DontMarkWeakMemberInConstruction) {
|
||||
MutatorThreadMarkingVisitor visitor(GetMarker());
|
||||
GCedWithInConstructionCallback* gced =
|
||||
MakeGarbageCollected<GCedWithInConstructionCallback>(
|
||||
GetHeap(), [&visitor](GCedWithInConstructionCallback* obj) {
|
||||
GetAllocationHandle(),
|
||||
[&visitor](GCedWithInConstructionCallback* obj) {
|
||||
WeakMember<GCedWithInConstructionCallback> object(obj);
|
||||
visitor.Trace(object);
|
||||
});
|
||||
@ -235,7 +243,8 @@ TEST_F(MarkingVisitorTest, DontMarkWeakMemberMixinInConstruction) {
|
||||
MutatorThreadMarkingVisitor visitor(GetMarker());
|
||||
GCedWithMixinWithInConstructionCallback* gced =
|
||||
MakeGarbageCollected<GCedWithMixinWithInConstructionCallback>(
|
||||
GetHeap(), [&visitor](MixinWithInConstructionCallback* obj) {
|
||||
GetAllocationHandle(),
|
||||
[&visitor](MixinWithInConstructionCallback* obj) {
|
||||
WeakMember<MixinWithInConstructionCallback> mixin(obj);
|
||||
visitor.Trace(mixin);
|
||||
});
|
||||
@ -246,7 +255,8 @@ TEST_F(MarkingVisitorTest, DontMarkPersistentInConstruction) {
|
||||
MutatorThreadMarkingVisitor visitor(GetMarker());
|
||||
GCedWithInConstructionCallback* gced =
|
||||
MakeGarbageCollected<GCedWithInConstructionCallback>(
|
||||
GetHeap(), [&visitor](GCedWithInConstructionCallback* obj) {
|
||||
GetAllocationHandle(),
|
||||
[&visitor](GCedWithInConstructionCallback* obj) {
|
||||
Persistent<GCedWithInConstructionCallback> object(obj);
|
||||
visitor.TraceRootForTesting(object, SourceLocation::Current());
|
||||
});
|
||||
@ -257,7 +267,8 @@ TEST_F(MarkingVisitorTest, DontMarkPersistentMixinInConstruction) {
|
||||
MutatorThreadMarkingVisitor visitor(GetMarker());
|
||||
GCedWithMixinWithInConstructionCallback* gced =
|
||||
MakeGarbageCollected<GCedWithMixinWithInConstructionCallback>(
|
||||
GetHeap(), [&visitor](MixinWithInConstructionCallback* obj) {
|
||||
GetAllocationHandle(),
|
||||
[&visitor](MixinWithInConstructionCallback* obj) {
|
||||
Persistent<MixinWithInConstructionCallback> mixin(obj);
|
||||
visitor.TraceRootForTesting(mixin, SourceLocation::Current());
|
||||
});
|
||||
@ -268,7 +279,8 @@ TEST_F(MarkingVisitorTest, DontMarkWeakPersistentInConstruction) {
|
||||
MutatorThreadMarkingVisitor visitor(GetMarker());
|
||||
GCedWithInConstructionCallback* gced =
|
||||
MakeGarbageCollected<GCedWithInConstructionCallback>(
|
||||
GetHeap(), [&visitor](GCedWithInConstructionCallback* obj) {
|
||||
GetAllocationHandle(),
|
||||
[&visitor](GCedWithInConstructionCallback* obj) {
|
||||
WeakPersistent<GCedWithInConstructionCallback> object(obj);
|
||||
visitor.TraceRootForTesting(object, SourceLocation::Current());
|
||||
});
|
||||
@ -279,7 +291,8 @@ TEST_F(MarkingVisitorTest, DontMarkWeakPersistentMixinInConstruction) {
|
||||
MutatorThreadMarkingVisitor visitor(GetMarker());
|
||||
GCedWithMixinWithInConstructionCallback* gced =
|
||||
MakeGarbageCollected<GCedWithMixinWithInConstructionCallback>(
|
||||
GetHeap(), [&visitor](MixinWithInConstructionCallback* obj) {
|
||||
GetAllocationHandle(),
|
||||
[&visitor](MixinWithInConstructionCallback* obj) {
|
||||
WeakPersistent<MixinWithInConstructionCallback> mixin(obj);
|
||||
visitor.TraceRootForTesting(mixin, SourceLocation::Current());
|
||||
});
|
||||
|
@ -87,7 +87,8 @@ TEST_F(MemberTest, Empty) {
|
||||
|
||||
template <template <typename> class MemberType>
|
||||
void ClearTest(cppgc::Heap* heap) {
|
||||
MemberType<GCed> member = MakeGarbageCollected<GCed>(heap);
|
||||
MemberType<GCed> member =
|
||||
MakeGarbageCollected<GCed>(heap->GetAllocationHandle());
|
||||
EXPECT_NE(nullptr, member.Get());
|
||||
member.Clear();
|
||||
EXPECT_EQ(nullptr, member.Get());
|
||||
@ -102,7 +103,7 @@ TEST_F(MemberTest, Clear) {
|
||||
|
||||
template <template <typename> class MemberType>
|
||||
void ReleaseTest(cppgc::Heap* heap) {
|
||||
GCed* gced = MakeGarbageCollected<GCed>(heap);
|
||||
GCed* gced = MakeGarbageCollected<GCed>(heap->GetAllocationHandle());
|
||||
MemberType<GCed> member = gced;
|
||||
EXPECT_NE(nullptr, member.Get());
|
||||
GCed* raw = member.Release();
|
||||
@ -120,8 +121,8 @@ TEST_F(MemberTest, Release) {
|
||||
template <template <typename> class MemberType1,
|
||||
template <typename> class MemberType2>
|
||||
void SwapTest(cppgc::Heap* heap) {
|
||||
GCed* gced1 = MakeGarbageCollected<GCed>(heap);
|
||||
GCed* gced2 = MakeGarbageCollected<GCed>(heap);
|
||||
GCed* gced1 = MakeGarbageCollected<GCed>(heap->GetAllocationHandle());
|
||||
GCed* gced2 = MakeGarbageCollected<GCed>(heap->GetAllocationHandle());
|
||||
MemberType1<GCed> member1 = gced1;
|
||||
MemberType2<GCed> member2 = gced2;
|
||||
EXPECT_EQ(gced1, member1.Get());
|
||||
@ -148,23 +149,27 @@ template <template <typename> class MemberType1,
|
||||
template <typename> class MemberType2>
|
||||
void HeterogeneousConversionTest(cppgc::Heap* heap) {
|
||||
{
|
||||
MemberType1<GCed> member1 = MakeGarbageCollected<GCed>(heap);
|
||||
MemberType1<GCed> member1 =
|
||||
MakeGarbageCollected<GCed>(heap->GetAllocationHandle());
|
||||
MemberType2<GCed> member2 = member1;
|
||||
EXPECT_EQ(member1.Get(), member2.Get());
|
||||
}
|
||||
{
|
||||
MemberType1<DerivedGCed> member1 = MakeGarbageCollected<DerivedGCed>(heap);
|
||||
MemberType1<DerivedGCed> member1 =
|
||||
MakeGarbageCollected<DerivedGCed>(heap->GetAllocationHandle());
|
||||
MemberType2<GCed> member2 = member1;
|
||||
EXPECT_EQ(member1.Get(), member2.Get());
|
||||
}
|
||||
{
|
||||
MemberType1<GCed> member1 = MakeGarbageCollected<GCed>(heap);
|
||||
MemberType1<GCed> member1 =
|
||||
MakeGarbageCollected<GCed>(heap->GetAllocationHandle());
|
||||
MemberType2<GCed> member2;
|
||||
member2 = member1;
|
||||
EXPECT_EQ(member1.Get(), member2.Get());
|
||||
}
|
||||
{
|
||||
MemberType1<DerivedGCed> member1 = MakeGarbageCollected<DerivedGCed>(heap);
|
||||
MemberType1<DerivedGCed> member1 =
|
||||
MakeGarbageCollected<DerivedGCed>(heap->GetAllocationHandle());
|
||||
MemberType2<GCed> member2;
|
||||
member2 = member1;
|
||||
EXPECT_EQ(member1.Get(), member2.Get());
|
||||
@ -188,25 +193,27 @@ template <template <typename> class MemberType,
|
||||
template <typename> class PersistentType>
|
||||
void PersistentConversionTest(cppgc::Heap* heap) {
|
||||
{
|
||||
PersistentType<GCed> persistent = MakeGarbageCollected<GCed>(heap);
|
||||
PersistentType<GCed> persistent =
|
||||
MakeGarbageCollected<GCed>(heap->GetAllocationHandle());
|
||||
MemberType<GCed> member = persistent;
|
||||
EXPECT_EQ(persistent.Get(), member.Get());
|
||||
}
|
||||
{
|
||||
PersistentType<DerivedGCed> persistent =
|
||||
MakeGarbageCollected<DerivedGCed>(heap);
|
||||
MakeGarbageCollected<DerivedGCed>(heap->GetAllocationHandle());
|
||||
MemberType<GCed> member = persistent;
|
||||
EXPECT_EQ(persistent.Get(), member.Get());
|
||||
}
|
||||
{
|
||||
PersistentType<GCed> persistent = MakeGarbageCollected<GCed>(heap);
|
||||
PersistentType<GCed> persistent =
|
||||
MakeGarbageCollected<GCed>(heap->GetAllocationHandle());
|
||||
MemberType<GCed> member;
|
||||
member = persistent;
|
||||
EXPECT_EQ(persistent.Get(), member.Get());
|
||||
}
|
||||
{
|
||||
PersistentType<DerivedGCed> persistent =
|
||||
MakeGarbageCollected<DerivedGCed>(heap);
|
||||
MakeGarbageCollected<DerivedGCed>(heap->GetAllocationHandle());
|
||||
MemberType<GCed> member;
|
||||
member = persistent;
|
||||
EXPECT_EQ(persistent.Get(), member.Get());
|
||||
@ -227,7 +234,7 @@ template <template <typename> class MemberType1,
|
||||
template <typename> class MemberType2>
|
||||
void EqualityTest(cppgc::Heap* heap) {
|
||||
{
|
||||
GCed* gced = MakeGarbageCollected<GCed>(heap);
|
||||
GCed* gced = MakeGarbageCollected<GCed>(heap->GetAllocationHandle());
|
||||
MemberType1<GCed> member1 = gced;
|
||||
MemberType2<GCed> member2 = gced;
|
||||
EXPECT_TRUE(member1 == member2);
|
||||
@ -237,8 +244,10 @@ void EqualityTest(cppgc::Heap* heap) {
|
||||
EXPECT_FALSE(member1 != member2);
|
||||
}
|
||||
{
|
||||
MemberType1<GCed> member1 = MakeGarbageCollected<GCed>(heap);
|
||||
MemberType2<GCed> member2 = MakeGarbageCollected<GCed>(heap);
|
||||
MemberType1<GCed> member1 =
|
||||
MakeGarbageCollected<GCed>(heap->GetAllocationHandle());
|
||||
MemberType2<GCed> member2 =
|
||||
MakeGarbageCollected<GCed>(heap->GetAllocationHandle());
|
||||
EXPECT_TRUE(member1 != member2);
|
||||
EXPECT_FALSE(member1 == member2);
|
||||
}
|
||||
@ -260,7 +269,7 @@ TEST_F(MemberTest, EqualityTest) {
|
||||
TEST_F(MemberTest, WriteBarrierTriggered) {
|
||||
CustomWriteBarrierPolicy::InitializingWriteBarriersTriggered = 0;
|
||||
CustomWriteBarrierPolicy::AssigningWriteBarriersTriggered = 0;
|
||||
GCed* gced = MakeGarbageCollected<GCed>(GetHeap());
|
||||
GCed* gced = MakeGarbageCollected<GCed>(GetAllocationHandle());
|
||||
MemberWithCustomBarrier member1 = gced;
|
||||
EXPECT_EQ(1u, CustomWriteBarrierPolicy::InitializingWriteBarriersTriggered);
|
||||
EXPECT_EQ(0u, CustomWriteBarrierPolicy::AssigningWriteBarriersTriggered);
|
||||
@ -290,7 +299,7 @@ TEST_F(MemberTest, CheckingPolicy) {
|
||||
|
||||
for (std::size_t i = 0; i < kElements; ++i) {
|
||||
CustomCheckingPolicy::Cached.push_back(
|
||||
MakeGarbageCollected<GCed>(GetHeap()));
|
||||
MakeGarbageCollected<GCed>(GetAllocationHandle()));
|
||||
}
|
||||
|
||||
MemberWithCustomChecking member;
|
||||
|
@ -114,7 +114,7 @@ TEST_F(PersistentTest, NullStateCtor) {
|
||||
template <template <typename> class PersistentType>
|
||||
void RawCtor(cppgc::Heap* heap) {
|
||||
EXPECT_EQ(0u, GetRegion<PersistentType>(heap).NodesInUse());
|
||||
GCed* gced = MakeGarbageCollected<GCed>(heap);
|
||||
GCed* gced = MakeGarbageCollected<GCed>(heap->GetAllocationHandle());
|
||||
{
|
||||
PersistentType<GCed> p = gced;
|
||||
EXPECT_EQ(gced, p.Get());
|
||||
@ -139,7 +139,8 @@ template <template <typename> class PersistentType>
|
||||
void CopyCtor(cppgc::Heap* heap) {
|
||||
EXPECT_EQ(0u, GetRegion<PersistentType>(heap).NodesInUse());
|
||||
{
|
||||
PersistentType<GCed> p1 = MakeGarbageCollected<GCed>(heap);
|
||||
PersistentType<GCed> p1 =
|
||||
MakeGarbageCollected<GCed>(heap->GetAllocationHandle());
|
||||
EXPECT_EQ(1u, GetRegion<PersistentType>(heap).NodesInUse());
|
||||
PersistentType<GCed> p2 = p1;
|
||||
EXPECT_EQ(2u, GetRegion<PersistentType>(heap).NodesInUse());
|
||||
@ -157,7 +158,8 @@ void CopyCtor(cppgc::Heap* heap) {
|
||||
}
|
||||
EXPECT_EQ(0u, GetRegion<PersistentType>(heap).NodesInUse());
|
||||
{
|
||||
PersistentType<DerivedGCed> p1 = MakeGarbageCollected<DerivedGCed>(heap);
|
||||
PersistentType<DerivedGCed> p1 =
|
||||
MakeGarbageCollected<DerivedGCed>(heap->GetAllocationHandle());
|
||||
EXPECT_EQ(1u, GetRegion<PersistentType>(heap).NodesInUse());
|
||||
PersistentType<GCed> p2 = p1;
|
||||
EXPECT_EQ(2u, GetRegion<PersistentType>(heap).NodesInUse());
|
||||
@ -167,7 +169,8 @@ void CopyCtor(cppgc::Heap* heap) {
|
||||
EXPECT_EQ(0u, GetRegion<PersistentType>(heap).NodesInUse());
|
||||
{
|
||||
static constexpr size_t kSlots = 512u;
|
||||
const PersistentType<GCed> prototype = MakeGarbageCollected<GCed>(heap);
|
||||
const PersistentType<GCed> prototype =
|
||||
MakeGarbageCollected<GCed>(heap->GetAllocationHandle());
|
||||
std::vector<PersistentType<GCed>> vector;
|
||||
vector.reserve(kSlots);
|
||||
EXPECT_EQ(1u, GetRegion<PersistentType>(heap).NodesInUse());
|
||||
@ -191,7 +194,7 @@ template <template <typename> class PersistentType>
|
||||
void MoveCtor(cppgc::Heap* heap) {
|
||||
EXPECT_EQ(0u, GetRegion<PersistentType>(heap).NodesInUse());
|
||||
{
|
||||
GCed* gced = MakeGarbageCollected<GCed>(heap);
|
||||
GCed* gced = MakeGarbageCollected<GCed>(heap->GetAllocationHandle());
|
||||
PersistentType<GCed> p1 = gced;
|
||||
EXPECT_EQ(1u, GetRegion<PersistentType>(heap).NodesInUse());
|
||||
PersistentType<GCed> p2 = std::move(p1);
|
||||
@ -202,7 +205,8 @@ void MoveCtor(cppgc::Heap* heap) {
|
||||
}
|
||||
EXPECT_EQ(0u, GetRegion<PersistentType>(heap).NodesInUse());
|
||||
{
|
||||
PersistentType<DerivedGCed> p1 = MakeGarbageCollected<DerivedGCed>(heap);
|
||||
PersistentType<DerivedGCed> p1 =
|
||||
MakeGarbageCollected<DerivedGCed>(heap->GetAllocationHandle());
|
||||
EXPECT_EQ(1u, GetRegion<PersistentType>(heap).NodesInUse());
|
||||
// Move ctor is not heterogeneous - fall back to copy ctor.
|
||||
PersistentType<GCed> p2 = std::move(p1);
|
||||
@ -233,7 +237,8 @@ template <template <typename> class PersistentType,
|
||||
void MemberCtor(cppgc::Heap* heap) {
|
||||
EXPECT_EQ(0u, GetRegion<PersistentType>(heap).NodesInUse());
|
||||
{
|
||||
MemberType<GCed> m = MakeGarbageCollected<GCed>(heap);
|
||||
MemberType<GCed> m =
|
||||
MakeGarbageCollected<GCed>(heap->GetAllocationHandle());
|
||||
PersistentType<GCed> p = m;
|
||||
EXPECT_EQ(m.Get(), p.Get());
|
||||
EXPECT_EQ(m, p);
|
||||
@ -256,14 +261,16 @@ template <template <typename> class PersistentType>
|
||||
void NullStateAssignemnt(cppgc::Heap* heap) {
|
||||
EXPECT_EQ(0u, GetRegion<PersistentType>(heap).NodesInUse());
|
||||
{
|
||||
PersistentType<GCed> p = MakeGarbageCollected<GCed>(heap);
|
||||
PersistentType<GCed> p =
|
||||
MakeGarbageCollected<GCed>(heap->GetAllocationHandle());
|
||||
EXPECT_EQ(1u, GetRegion<PersistentType>(heap).NodesInUse());
|
||||
p = nullptr;
|
||||
EXPECT_EQ(nullptr, p.Get());
|
||||
EXPECT_EQ(0u, GetRegion<PersistentType>(heap).NodesInUse());
|
||||
}
|
||||
{
|
||||
PersistentType<GCed> p = MakeGarbageCollected<GCed>(heap);
|
||||
PersistentType<GCed> p =
|
||||
MakeGarbageCollected<GCed>(heap->GetAllocationHandle());
|
||||
EXPECT_EQ(1u, GetRegion<PersistentType>(heap).NodesInUse());
|
||||
p = kSentinelPointer;
|
||||
EXPECT_EQ(kSentinelPointer, p);
|
||||
@ -271,7 +278,8 @@ void NullStateAssignemnt(cppgc::Heap* heap) {
|
||||
EXPECT_EQ(0u, GetRegion<PersistentType>(heap).NodesInUse());
|
||||
}
|
||||
{
|
||||
PersistentType<GCed> p = MakeGarbageCollected<GCed>(heap);
|
||||
PersistentType<GCed> p =
|
||||
MakeGarbageCollected<GCed>(heap->GetAllocationHandle());
|
||||
EXPECT_EQ(1u, GetRegion<PersistentType>(heap).NodesInUse());
|
||||
p = static_cast<GCed*>(0);
|
||||
EXPECT_EQ(nullptr, p.Get());
|
||||
@ -288,7 +296,7 @@ TEST_F(PersistentTest, NullStateAssignemnt) {
|
||||
template <template <typename> class PersistentType>
|
||||
void RawAssignment(cppgc::Heap* heap) {
|
||||
EXPECT_EQ(0u, GetRegion<PersistentType>(heap).NodesInUse());
|
||||
GCed* gced = MakeGarbageCollected<GCed>(heap);
|
||||
GCed* gced = MakeGarbageCollected<GCed>(heap->GetAllocationHandle());
|
||||
{
|
||||
PersistentType<GCed> p;
|
||||
EXPECT_EQ(0u, GetRegion<PersistentType>(heap).NodesInUse());
|
||||
@ -317,7 +325,8 @@ template <template <typename> class PersistentType>
|
||||
void CopyAssignment(cppgc::Heap* heap) {
|
||||
EXPECT_EQ(0u, GetRegion<PersistentType>(heap).NodesInUse());
|
||||
{
|
||||
PersistentType<GCed> p1 = MakeGarbageCollected<GCed>(heap);
|
||||
PersistentType<GCed> p1 =
|
||||
MakeGarbageCollected<GCed>(heap->GetAllocationHandle());
|
||||
PersistentType<GCed> p2;
|
||||
EXPECT_EQ(1u, GetRegion<PersistentType>(heap).NodesInUse());
|
||||
p2 = p1;
|
||||
@ -327,8 +336,10 @@ void CopyAssignment(cppgc::Heap* heap) {
|
||||
}
|
||||
EXPECT_EQ(0u, GetRegion<PersistentType>(heap).NodesInUse());
|
||||
{
|
||||
PersistentType<GCed> p1 = MakeGarbageCollected<GCed>(heap);
|
||||
PersistentType<GCed> p2 = MakeGarbageCollected<GCed>(heap);
|
||||
PersistentType<GCed> p1 =
|
||||
MakeGarbageCollected<GCed>(heap->GetAllocationHandle());
|
||||
PersistentType<GCed> p2 =
|
||||
MakeGarbageCollected<GCed>(heap->GetAllocationHandle());
|
||||
EXPECT_EQ(2u, GetRegion<PersistentType>(heap).NodesInUse());
|
||||
p2 = p1;
|
||||
// The old node from p2 must be dropped.
|
||||
@ -338,7 +349,8 @@ void CopyAssignment(cppgc::Heap* heap) {
|
||||
}
|
||||
EXPECT_EQ(0u, GetRegion<PersistentType>(heap).NodesInUse());
|
||||
{
|
||||
PersistentType<DerivedGCed> p1 = MakeGarbageCollected<DerivedGCed>(heap);
|
||||
PersistentType<DerivedGCed> p1 =
|
||||
MakeGarbageCollected<DerivedGCed>(heap->GetAllocationHandle());
|
||||
PersistentType<GCed> p2;
|
||||
EXPECT_EQ(1u, GetRegion<PersistentType>(heap).NodesInUse());
|
||||
p2 = p1;
|
||||
@ -349,7 +361,8 @@ void CopyAssignment(cppgc::Heap* heap) {
|
||||
EXPECT_EQ(0u, GetRegion<PersistentType>(heap).NodesInUse());
|
||||
{
|
||||
static constexpr size_t kSlots = 512u;
|
||||
const PersistentType<GCed> prototype = MakeGarbageCollected<GCed>(heap);
|
||||
const PersistentType<GCed> prototype =
|
||||
MakeGarbageCollected<GCed>(heap->GetAllocationHandle());
|
||||
std::vector<PersistentType<GCed>> vector(kSlots);
|
||||
EXPECT_EQ(1u, GetRegion<PersistentType>(heap).NodesInUse());
|
||||
size_t i = 0;
|
||||
@ -374,7 +387,7 @@ template <template <typename> class PersistentType>
|
||||
void MoveAssignment(cppgc::Heap* heap) {
|
||||
EXPECT_EQ(0u, GetRegion<PersistentType>(heap).NodesInUse());
|
||||
{
|
||||
GCed* gced = MakeGarbageCollected<GCed>(heap);
|
||||
GCed* gced = MakeGarbageCollected<GCed>(heap->GetAllocationHandle());
|
||||
PersistentType<GCed> p1 = gced;
|
||||
PersistentType<GCed> p2;
|
||||
EXPECT_EQ(1u, GetRegion<PersistentType>(heap).NodesInUse());
|
||||
@ -387,7 +400,8 @@ void MoveAssignment(cppgc::Heap* heap) {
|
||||
EXPECT_EQ(0u, GetRegion<PersistentType>(heap).NodesInUse());
|
||||
{
|
||||
PersistentType<GCed> p1;
|
||||
PersistentType<GCed> p2 = MakeGarbageCollected<GCed>(heap);
|
||||
PersistentType<GCed> p2 =
|
||||
MakeGarbageCollected<GCed>(heap->GetAllocationHandle());
|
||||
EXPECT_EQ(1u, GetRegion<PersistentType>(heap).NodesInUse());
|
||||
p2 = std::move(p1);
|
||||
EXPECT_EQ(0u, GetRegion<PersistentType>(heap).NodesInUse());
|
||||
@ -396,9 +410,10 @@ void MoveAssignment(cppgc::Heap* heap) {
|
||||
}
|
||||
EXPECT_EQ(0u, GetRegion<PersistentType>(heap).NodesInUse());
|
||||
{
|
||||
GCed* gced = MakeGarbageCollected<GCed>(heap);
|
||||
GCed* gced = MakeGarbageCollected<GCed>(heap->GetAllocationHandle());
|
||||
PersistentType<GCed> p1 = gced;
|
||||
PersistentType<GCed> p2 = MakeGarbageCollected<GCed>(heap);
|
||||
PersistentType<GCed> p2 =
|
||||
MakeGarbageCollected<GCed>(heap->GetAllocationHandle());
|
||||
EXPECT_EQ(2u, GetRegion<PersistentType>(heap).NodesInUse());
|
||||
p2 = std::move(p1);
|
||||
// The old node from p2 must be dropped.
|
||||
@ -409,7 +424,8 @@ void MoveAssignment(cppgc::Heap* heap) {
|
||||
}
|
||||
EXPECT_EQ(0u, GetRegion<PersistentType>(heap).NodesInUse());
|
||||
{
|
||||
PersistentType<DerivedGCed> p1 = MakeGarbageCollected<DerivedGCed>(heap);
|
||||
PersistentType<DerivedGCed> p1 =
|
||||
MakeGarbageCollected<DerivedGCed>(heap->GetAllocationHandle());
|
||||
PersistentType<GCed> p2;
|
||||
EXPECT_EQ(1u, GetRegion<PersistentType>(heap).NodesInUse());
|
||||
// Move ctor is not heterogeneous - fall back to copy assignment.
|
||||
@ -432,7 +448,8 @@ template <template <typename> class PersistentType,
|
||||
void MemberAssignment(cppgc::Heap* heap) {
|
||||
EXPECT_EQ(0u, GetRegion<PersistentType>(heap).NodesInUse());
|
||||
{
|
||||
MemberType<GCed> m = MakeGarbageCollected<GCed>(heap);
|
||||
MemberType<GCed> m =
|
||||
MakeGarbageCollected<GCed>(heap->GetAllocationHandle());
|
||||
PersistentType<GCed> p;
|
||||
p = m;
|
||||
EXPECT_EQ(m.Get(), p.Get());
|
||||
@ -455,7 +472,8 @@ TEST_F(PersistentTest, MemberAssignment) {
|
||||
template <template <typename> class PersistentType>
|
||||
void ClearTest(cppgc::Heap* heap) {
|
||||
EXPECT_EQ(0u, GetRegion<PersistentType>(heap).NodesInUse());
|
||||
PersistentType<GCed> p = MakeGarbageCollected<GCed>(heap);
|
||||
PersistentType<GCed> p =
|
||||
MakeGarbageCollected<GCed>(heap->GetAllocationHandle());
|
||||
EXPECT_EQ(1u, GetRegion<PersistentType>(heap).NodesInUse());
|
||||
EXPECT_NE(nullptr, p.Get());
|
||||
p.Clear();
|
||||
@ -472,7 +490,7 @@ TEST_F(PersistentTest, Clear) {
|
||||
template <template <typename> class PersistentType>
|
||||
void ReleaseTest(cppgc::Heap* heap) {
|
||||
EXPECT_EQ(0u, GetRegion<PersistentType>(heap).NodesInUse());
|
||||
GCed* gced = MakeGarbageCollected<GCed>(heap);
|
||||
GCed* gced = MakeGarbageCollected<GCed>(heap->GetAllocationHandle());
|
||||
PersistentType<GCed> p = gced;
|
||||
EXPECT_EQ(1u, GetRegion<PersistentType>(heap).NodesInUse());
|
||||
EXPECT_NE(nullptr, p.Get());
|
||||
@ -494,7 +512,8 @@ void HeterogeneousConversion(cppgc::Heap* heap) {
|
||||
EXPECT_EQ(0u, GetRegion<PersistentType1>(heap).NodesInUse());
|
||||
EXPECT_EQ(0u, GetRegion<PersistentType2>(heap).NodesInUse());
|
||||
{
|
||||
PersistentType1<GCed> persistent1 = MakeGarbageCollected<GCed>(heap);
|
||||
PersistentType1<GCed> persistent1 =
|
||||
MakeGarbageCollected<GCed>(heap->GetAllocationHandle());
|
||||
PersistentType2<GCed> persistent2 = persistent1;
|
||||
EXPECT_EQ(persistent1.Get(), persistent2.Get());
|
||||
EXPECT_EQ(1u, GetRegion<PersistentType1>(heap).NodesInUse());
|
||||
@ -504,7 +523,7 @@ void HeterogeneousConversion(cppgc::Heap* heap) {
|
||||
EXPECT_EQ(0u, GetRegion<PersistentType2>(heap).NodesInUse());
|
||||
{
|
||||
PersistentType1<DerivedGCed> persistent1 =
|
||||
MakeGarbageCollected<DerivedGCed>(heap);
|
||||
MakeGarbageCollected<DerivedGCed>(heap->GetAllocationHandle());
|
||||
PersistentType2<GCed> persistent2 = persistent1;
|
||||
EXPECT_EQ(persistent1.Get(), persistent2.Get());
|
||||
EXPECT_EQ(1u, GetRegion<PersistentType1>(heap).NodesInUse());
|
||||
@ -513,7 +532,8 @@ void HeterogeneousConversion(cppgc::Heap* heap) {
|
||||
EXPECT_EQ(0u, GetRegion<PersistentType1>(heap).NodesInUse());
|
||||
EXPECT_EQ(0u, GetRegion<PersistentType2>(heap).NodesInUse());
|
||||
{
|
||||
PersistentType1<GCed> persistent1 = MakeGarbageCollected<GCed>(heap);
|
||||
PersistentType1<GCed> persistent1 =
|
||||
MakeGarbageCollected<GCed>(heap->GetAllocationHandle());
|
||||
PersistentType2<GCed> persistent2;
|
||||
persistent2 = persistent1;
|
||||
EXPECT_EQ(persistent1.Get(), persistent2.Get());
|
||||
@ -524,7 +544,7 @@ void HeterogeneousConversion(cppgc::Heap* heap) {
|
||||
EXPECT_EQ(0u, GetRegion<PersistentType2>(heap).NodesInUse());
|
||||
{
|
||||
PersistentType1<DerivedGCed> persistent1 =
|
||||
MakeGarbageCollected<DerivedGCed>(heap);
|
||||
MakeGarbageCollected<DerivedGCed>(heap->GetAllocationHandle());
|
||||
PersistentType2<GCed> persistent2;
|
||||
persistent2 = persistent1;
|
||||
EXPECT_EQ(persistent1.Get(), persistent2.Get());
|
||||
@ -546,7 +566,7 @@ TEST_F(PersistentTest, TraceStrong) {
|
||||
static constexpr size_t kItems = 512;
|
||||
std::vector<Persistent<GCed>> vec(kItems);
|
||||
for (auto& p : vec) {
|
||||
p = MakeGarbageCollected<GCed>(heap);
|
||||
p = MakeGarbageCollected<GCed>(GetAllocationHandle());
|
||||
}
|
||||
{
|
||||
GCed::trace_call_count = 0;
|
||||
@ -581,7 +601,7 @@ TEST_F(PersistentTest, TraceWeak) {
|
||||
static constexpr size_t kItems = 512;
|
||||
std::vector<WeakPersistent<GCed>> vec(kItems);
|
||||
for (auto& p : vec) {
|
||||
p = MakeGarbageCollected<GCed>(heap);
|
||||
p = MakeGarbageCollected<GCed>(GetAllocationHandle());
|
||||
}
|
||||
GCed::trace_call_count = 0;
|
||||
RootVisitor v;
|
||||
@ -599,7 +619,7 @@ TEST_F(PersistentTest, TraceWeak) {
|
||||
|
||||
#if CPPGC_SUPPORTS_SOURCE_LOCATION
|
||||
TEST_F(PersistentTest, LocalizedPersistent) {
|
||||
GCed* gced = MakeGarbageCollected<GCed>(GetHeap());
|
||||
GCed* gced = MakeGarbageCollected<GCed>(GetAllocationHandle());
|
||||
{
|
||||
const auto expected_loc = SourceLocation::Current();
|
||||
LocalizedPersistent<GCed> p = gced;
|
||||
|
@ -33,7 +33,7 @@ size_t GCed::prefinalizer_callcount = 0;
|
||||
|
||||
TEST_F(PrefinalizerTest, PrefinalizerCalledOnDeadObject) {
|
||||
GCed::prefinalizer_callcount = 0;
|
||||
auto* object = MakeGarbageCollected<GCed>(GetHeap());
|
||||
auto* object = MakeGarbageCollected<GCed>(GetAllocationHandle());
|
||||
USE(object);
|
||||
EXPECT_EQ(0u, GCed::prefinalizer_callcount);
|
||||
PreciseGC();
|
||||
@ -44,7 +44,7 @@ TEST_F(PrefinalizerTest, PrefinalizerCalledOnDeadObject) {
|
||||
|
||||
TEST_F(PrefinalizerTest, PrefinalizerNotCalledOnLiveObject) {
|
||||
GCed::prefinalizer_callcount = 0;
|
||||
auto* object = MakeGarbageCollected<GCed>(GetHeap());
|
||||
auto* object = MakeGarbageCollected<GCed>(GetAllocationHandle());
|
||||
HeapObjectHeader::FromPayload(object).TryMarkAtomic();
|
||||
EXPECT_EQ(0u, GCed::prefinalizer_callcount);
|
||||
PreciseGC();
|
||||
@ -73,7 +73,7 @@ class GCedWithMixin : public GarbageCollected<GCedWithMixin>, public Mixin {
|
||||
|
||||
TEST_F(PrefinalizerTest, PrefinalizerCalledOnDeadMixinObject) {
|
||||
Mixin::prefinalizer_callcount = 0;
|
||||
auto* object = MakeGarbageCollected<GCedWithMixin>(GetHeap());
|
||||
auto* object = MakeGarbageCollected<GCedWithMixin>(GetAllocationHandle());
|
||||
USE(object);
|
||||
EXPECT_EQ(0u, Mixin::prefinalizer_callcount);
|
||||
PreciseGC();
|
||||
@ -84,7 +84,7 @@ TEST_F(PrefinalizerTest, PrefinalizerCalledOnDeadMixinObject) {
|
||||
|
||||
TEST_F(PrefinalizerTest, PrefinalizerNotCalledOnLiveMixinObject) {
|
||||
Mixin::prefinalizer_callcount = 0;
|
||||
auto* object = MakeGarbageCollected<GCedWithMixin>(GetHeap());
|
||||
auto* object = MakeGarbageCollected<GCedWithMixin>(GetAllocationHandle());
|
||||
HeapObjectHeader::FromPayload(object).TryMarkAtomic();
|
||||
EXPECT_EQ(0u, Mixin::prefinalizer_callcount);
|
||||
PreciseGC();
|
||||
@ -153,7 +153,7 @@ TEST_F(PrefinalizerTest, PrefinalizerInvocationPreservesOrder) {
|
||||
BaseMixin::prefinalizer_callcount = 0;
|
||||
InheritingMixin::prefinalizer_callcount = 0;
|
||||
GCedWithMixins::prefinalizer_callcount = 0;
|
||||
auto* object = MakeGarbageCollected<GCedWithMixins>(GetHeap());
|
||||
auto* object = MakeGarbageCollected<GCedWithMixins>(GetAllocationHandle());
|
||||
USE(object);
|
||||
EXPECT_EQ(0u, GCedWithMixins::prefinalizer_callcount);
|
||||
EXPECT_EQ(0u, InheritingMixin::prefinalizer_callcount);
|
||||
@ -176,7 +176,9 @@ class AllocatingPrefinalizer : public GarbageCollected<AllocatingPrefinalizer> {
|
||||
public:
|
||||
explicit AllocatingPrefinalizer(cppgc::Heap* heap) : heap_(heap) {}
|
||||
void Trace(Visitor*) const {}
|
||||
void PreFinalizer() { MakeGarbageCollected<GCed>(heap_); }
|
||||
void PreFinalizer() {
|
||||
MakeGarbageCollected<GCed>(heap_->GetAllocationHandle());
|
||||
}
|
||||
|
||||
private:
|
||||
cppgc::Heap* heap_;
|
||||
@ -187,8 +189,8 @@ class AllocatingPrefinalizer : public GarbageCollected<AllocatingPrefinalizer> {
|
||||
#ifdef DEBUG
|
||||
|
||||
TEST_F(PrefinalizerTest, PrefinalizerFailsOnAllcoation) {
|
||||
auto* object =
|
||||
MakeGarbageCollected<AllocatingPrefinalizer>(GetHeap(), GetHeap());
|
||||
auto* object = MakeGarbageCollected<AllocatingPrefinalizer>(
|
||||
GetAllocationHandle(), GetHeap());
|
||||
USE(object);
|
||||
EXPECT_DEATH_IF_SUPPORTED(PreciseGC(), "");
|
||||
}
|
||||
|
@ -68,7 +68,7 @@ TEST_F(SweeperTest, SweepUnmarkedNormalObject) {
|
||||
constexpr size_t kObjectSize = 8;
|
||||
using Type = GCed<kObjectSize>;
|
||||
|
||||
MakeGarbageCollected<Type>(GetHeap());
|
||||
MakeGarbageCollected<Type>(GetAllocationHandle());
|
||||
|
||||
EXPECT_EQ(0u, g_destructor_callcount);
|
||||
|
||||
@ -81,7 +81,7 @@ TEST_F(SweeperTest, DontSweepMarkedNormalObject) {
|
||||
constexpr size_t kObjectSize = 8;
|
||||
using Type = GCed<kObjectSize>;
|
||||
|
||||
auto* object = MakeGarbageCollected<Type>(GetHeap());
|
||||
auto* object = MakeGarbageCollected<Type>(GetAllocationHandle());
|
||||
MarkObject(object);
|
||||
BasePage* page = BasePage::FromPayload(object);
|
||||
BaseSpace* space = page->space();
|
||||
@ -100,7 +100,7 @@ TEST_F(SweeperTest, SweepUnmarkedLargeObject) {
|
||||
constexpr size_t kObjectSize = kLargeObjectSizeThreshold * 2;
|
||||
using Type = GCed<kObjectSize>;
|
||||
|
||||
auto* object = MakeGarbageCollected<Type>(GetHeap());
|
||||
auto* object = MakeGarbageCollected<Type>(GetAllocationHandle());
|
||||
BasePage* page = BasePage::FromPayload(object);
|
||||
BaseSpace* space = page->space();
|
||||
|
||||
@ -118,7 +118,7 @@ TEST_F(SweeperTest, DontSweepMarkedLargeObject) {
|
||||
constexpr size_t kObjectSize = kLargeObjectSizeThreshold * 2;
|
||||
using Type = GCed<kObjectSize>;
|
||||
|
||||
auto* object = MakeGarbageCollected<Type>(GetHeap());
|
||||
auto* object = MakeGarbageCollected<Type>(GetAllocationHandle());
|
||||
MarkObject(object);
|
||||
BasePage* page = BasePage::FromPayload(object);
|
||||
BaseSpace* space = page->space();
|
||||
@ -140,7 +140,7 @@ TEST_F(SweeperTest, SweepMultipleObjectsOnPage) {
|
||||
NormalPage::PayloadSize() / (sizeof(Type) + sizeof(HeapObjectHeader));
|
||||
|
||||
for (size_t i = 0; i < kNumberOfObjects; ++i) {
|
||||
MakeGarbageCollected<Type>(GetHeap());
|
||||
MakeGarbageCollected<Type>(GetAllocationHandle());
|
||||
}
|
||||
|
||||
EXPECT_EQ(0u, g_destructor_callcount);
|
||||
@ -151,11 +151,12 @@ TEST_F(SweeperTest, SweepMultipleObjectsOnPage) {
|
||||
}
|
||||
|
||||
TEST_F(SweeperTest, SweepObjectsOnAllArenas) {
|
||||
MakeGarbageCollected<GCed<1>>(GetHeap());
|
||||
MakeGarbageCollected<GCed<32>>(GetHeap());
|
||||
MakeGarbageCollected<GCed<64>>(GetHeap());
|
||||
MakeGarbageCollected<GCed<128>>(GetHeap());
|
||||
MakeGarbageCollected<GCed<2 * kLargeObjectSizeThreshold>>(GetHeap());
|
||||
MakeGarbageCollected<GCed<1>>(GetAllocationHandle());
|
||||
MakeGarbageCollected<GCed<32>>(GetAllocationHandle());
|
||||
MakeGarbageCollected<GCed<64>>(GetAllocationHandle());
|
||||
MakeGarbageCollected<GCed<128>>(GetAllocationHandle());
|
||||
MakeGarbageCollected<GCed<2 * kLargeObjectSizeThreshold>>(
|
||||
GetAllocationHandle());
|
||||
|
||||
EXPECT_EQ(0u, g_destructor_callcount);
|
||||
|
||||
@ -165,9 +166,12 @@ TEST_F(SweeperTest, SweepObjectsOnAllArenas) {
|
||||
}
|
||||
|
||||
TEST_F(SweeperTest, SweepMultiplePagesInSingleSpace) {
|
||||
MakeGarbageCollected<GCed<2 * kLargeObjectSizeThreshold>>(GetHeap());
|
||||
MakeGarbageCollected<GCed<2 * kLargeObjectSizeThreshold>>(GetHeap());
|
||||
MakeGarbageCollected<GCed<2 * kLargeObjectSizeThreshold>>(GetHeap());
|
||||
MakeGarbageCollected<GCed<2 * kLargeObjectSizeThreshold>>(
|
||||
GetAllocationHandle());
|
||||
MakeGarbageCollected<GCed<2 * kLargeObjectSizeThreshold>>(
|
||||
GetAllocationHandle());
|
||||
MakeGarbageCollected<GCed<2 * kLargeObjectSizeThreshold>>(
|
||||
GetAllocationHandle());
|
||||
|
||||
EXPECT_EQ(0u, g_destructor_callcount);
|
||||
|
||||
@ -180,10 +184,10 @@ TEST_F(SweeperTest, CoalesceFreeListEntries) {
|
||||
constexpr size_t kObjectSize = 32;
|
||||
using Type = GCed<kObjectSize>;
|
||||
|
||||
auto* object1 = MakeGarbageCollected<Type>(GetHeap());
|
||||
auto* object2 = MakeGarbageCollected<Type>(GetHeap());
|
||||
auto* object3 = MakeGarbageCollected<Type>(GetHeap());
|
||||
auto* object4 = MakeGarbageCollected<Type>(GetHeap());
|
||||
auto* object1 = MakeGarbageCollected<Type>(GetAllocationHandle());
|
||||
auto* object2 = MakeGarbageCollected<Type>(GetAllocationHandle());
|
||||
auto* object3 = MakeGarbageCollected<Type>(GetAllocationHandle());
|
||||
auto* object4 = MakeGarbageCollected<Type>(GetAllocationHandle());
|
||||
|
||||
MarkObject(object1);
|
||||
MarkObject(object4);
|
||||
@ -231,15 +235,16 @@ class GCInDestructor final : public GarbageCollected<GCInDestructor> {
|
||||
TEST_F(SweeperTest, SweepDoesNotTriggerRecursiveGC) {
|
||||
auto* internal_heap = internal::Heap::From(GetHeap());
|
||||
size_t saved_epoch = internal_heap->epoch();
|
||||
MakeGarbageCollected<GCInDestructor>(GetHeap(), internal_heap);
|
||||
MakeGarbageCollected<GCInDestructor>(GetAllocationHandle(), internal_heap);
|
||||
PreciseGC();
|
||||
EXPECT_EQ(saved_epoch + 1, internal_heap->epoch());
|
||||
}
|
||||
|
||||
TEST_F(SweeperTest, UnmarkObjects) {
|
||||
auto* normal_object = MakeGarbageCollected<GCed<32>>(GetHeap());
|
||||
auto* normal_object = MakeGarbageCollected<GCed<32>>(GetAllocationHandle());
|
||||
auto* large_object =
|
||||
MakeGarbageCollected<GCed<kLargeObjectSizeThreshold * 2>>(GetHeap());
|
||||
MakeGarbageCollected<GCed<kLargeObjectSizeThreshold * 2>>(
|
||||
GetAllocationHandle());
|
||||
|
||||
auto& normal_object_header = HeapObjectHeader::FromPayload(normal_object);
|
||||
auto& large_object_header = HeapObjectHeader::FromPayload(large_object);
|
||||
|
@ -28,7 +28,9 @@ void TestWithPlatform::TearDownTestSuite() {
|
||||
platform_.reset();
|
||||
}
|
||||
|
||||
TestWithHeap::TestWithHeap() : heap_(Heap::Create(platform_)) {}
|
||||
TestWithHeap::TestWithHeap()
|
||||
: heap_(Heap::Create(platform_)),
|
||||
allocation_handle_(heap_->GetAllocationHandle()) {}
|
||||
|
||||
void TestWithHeap::ResetLinearAllocationBuffers() {
|
||||
Heap::From(GetHeap())->object_allocator().ResetLinearAllocationBuffers();
|
||||
|
@ -37,6 +37,10 @@ class TestWithHeap : public TestWithPlatform {
|
||||
|
||||
cppgc::Heap* GetHeap() const { return heap_.get(); }
|
||||
|
||||
cppgc::AllocationHandle& GetAllocationHandle() const {
|
||||
return allocation_handle_;
|
||||
}
|
||||
|
||||
std::unique_ptr<Marker>& GetMarkerRef() {
|
||||
return Heap::From(GetHeap())->marker_;
|
||||
}
|
||||
@ -45,6 +49,7 @@ class TestWithHeap : public TestWithPlatform {
|
||||
|
||||
private:
|
||||
std::unique_ptr<cppgc::Heap> heap_;
|
||||
cppgc::AllocationHandle& allocation_handle_;
|
||||
};
|
||||
|
||||
// Restrictive test fixture that supports allocation but will make sure no
|
||||
|
@ -53,13 +53,14 @@ class GCedMixinApplication : public GCed,
|
||||
} // namespace
|
||||
|
||||
TEST_F(TraceTraitTest, GetObjectStartGCed) {
|
||||
auto* gced = MakeGarbageCollected<GCed>(GetHeap());
|
||||
auto* gced = MakeGarbageCollected<GCed>(GetAllocationHandle());
|
||||
EXPECT_EQ(gced,
|
||||
TraceTrait<GCed>::GetTraceDescriptor(gced).base_object_payload);
|
||||
}
|
||||
|
||||
TEST_F(TraceTraitTest, GetObjectStartGCedMixin) {
|
||||
auto* gced_mixin_app = MakeGarbageCollected<GCedMixinApplication>(GetHeap());
|
||||
auto* gced_mixin_app =
|
||||
MakeGarbageCollected<GCedMixinApplication>(GetAllocationHandle());
|
||||
auto* gced_mixin = static_cast<GCedMixin*>(gced_mixin_app);
|
||||
EXPECT_EQ(gced_mixin_app,
|
||||
TraceTrait<GCedMixin>::GetTraceDescriptor(gced_mixin)
|
||||
@ -67,14 +68,15 @@ TEST_F(TraceTraitTest, GetObjectStartGCedMixin) {
|
||||
}
|
||||
|
||||
TEST_F(TraceTraitTest, TraceGCed) {
|
||||
auto* gced = MakeGarbageCollected<GCed>(GetHeap());
|
||||
auto* gced = MakeGarbageCollected<GCed>(GetAllocationHandle());
|
||||
EXPECT_EQ(0u, GCed::trace_callcount);
|
||||
TraceTrait<GCed>::Trace(nullptr, gced);
|
||||
EXPECT_EQ(1u, GCed::trace_callcount);
|
||||
}
|
||||
|
||||
TEST_F(TraceTraitTest, TraceGCedMixin) {
|
||||
auto* gced_mixin_app = MakeGarbageCollected<GCedMixinApplication>(GetHeap());
|
||||
auto* gced_mixin_app =
|
||||
MakeGarbageCollected<GCedMixinApplication>(GetAllocationHandle());
|
||||
auto* gced_mixin = static_cast<GCedMixin*>(gced_mixin_app);
|
||||
EXPECT_EQ(0u, GCed::trace_callcount);
|
||||
TraceTrait<GCedMixin>::Trace(nullptr, gced_mixin);
|
||||
@ -82,7 +84,7 @@ TEST_F(TraceTraitTest, TraceGCedMixin) {
|
||||
}
|
||||
|
||||
TEST_F(TraceTraitTest, TraceGCedThroughTraceDescriptor) {
|
||||
auto* gced = MakeGarbageCollected<GCed>(GetHeap());
|
||||
auto* gced = MakeGarbageCollected<GCed>(GetAllocationHandle());
|
||||
EXPECT_EQ(0u, GCed::trace_callcount);
|
||||
TraceDescriptor desc = TraceTrait<GCed>::GetTraceDescriptor(gced);
|
||||
desc.callback(nullptr, desc.base_object_payload);
|
||||
@ -90,7 +92,8 @@ TEST_F(TraceTraitTest, TraceGCedThroughTraceDescriptor) {
|
||||
}
|
||||
|
||||
TEST_F(TraceTraitTest, TraceGCedMixinThroughTraceDescriptor) {
|
||||
auto* gced_mixin_app = MakeGarbageCollected<GCedMixinApplication>(GetHeap());
|
||||
auto* gced_mixin_app =
|
||||
MakeGarbageCollected<GCedMixinApplication>(GetAllocationHandle());
|
||||
auto* gced_mixin = static_cast<GCedMixin*>(gced_mixin_app);
|
||||
EXPECT_EQ(0u, GCed::trace_callcount);
|
||||
TraceDescriptor desc = TraceTrait<GCedMixin>::GetTraceDescriptor(gced_mixin);
|
||||
@ -128,7 +131,7 @@ class DispatchingVisitor final : public VisitorBase {
|
||||
} // namespace
|
||||
|
||||
TEST_F(VisitorTest, DispatchTraceGCed) {
|
||||
Member<GCed> ref = MakeGarbageCollected<GCed>(GetHeap());
|
||||
Member<GCed> ref = MakeGarbageCollected<GCed>(GetAllocationHandle());
|
||||
DispatchingVisitor visitor(ref, ref);
|
||||
EXPECT_EQ(0u, GCed::trace_callcount);
|
||||
visitor.Trace(ref);
|
||||
@ -136,7 +139,8 @@ TEST_F(VisitorTest, DispatchTraceGCed) {
|
||||
}
|
||||
|
||||
TEST_F(VisitorTest, DispatchTraceGCedMixin) {
|
||||
auto* gced_mixin_app = MakeGarbageCollected<GCedMixinApplication>(GetHeap());
|
||||
auto* gced_mixin_app =
|
||||
MakeGarbageCollected<GCedMixinApplication>(GetAllocationHandle());
|
||||
auto* gced_mixin = static_cast<GCedMixin*>(gced_mixin_app);
|
||||
// Ensure that we indeed test dispatching an inner object.
|
||||
EXPECT_NE(static_cast<void*>(gced_mixin_app), static_cast<void*>(gced_mixin));
|
||||
@ -148,7 +152,7 @@ TEST_F(VisitorTest, DispatchTraceGCedMixin) {
|
||||
}
|
||||
|
||||
TEST_F(VisitorTest, DispatchTraceWeakGCed) {
|
||||
WeakMember<GCed> ref = MakeGarbageCollected<GCed>(GetHeap());
|
||||
WeakMember<GCed> ref = MakeGarbageCollected<GCed>(GetAllocationHandle());
|
||||
DispatchingVisitor visitor(ref, ref);
|
||||
visitor.Trace(ref);
|
||||
// No marking, so reference should be cleared.
|
||||
@ -156,7 +160,8 @@ TEST_F(VisitorTest, DispatchTraceWeakGCed) {
|
||||
}
|
||||
|
||||
TEST_F(VisitorTest, DispatchTraceWeakGCedMixin) {
|
||||
auto* gced_mixin_app = MakeGarbageCollected<GCedMixinApplication>(GetHeap());
|
||||
auto* gced_mixin_app =
|
||||
MakeGarbageCollected<GCedMixinApplication>(GetAllocationHandle());
|
||||
auto* gced_mixin = static_cast<GCedMixin*>(gced_mixin_app);
|
||||
// Ensure that we indeed test dispatching an inner object.
|
||||
EXPECT_NE(static_cast<void*>(gced_mixin_app), static_cast<void*>(gced_mixin));
|
||||
@ -221,7 +226,8 @@ TEST_F(VisitorTest, DispatchRegisterWeakCallback) {
|
||||
|
||||
TEST_F(VisitorTest, DispatchRegisterWeakCallbackMethod) {
|
||||
WeakCallbackVisitor visitor;
|
||||
auto* gced = MakeGarbageCollected<GCedWithCustomWeakCallback>(GetHeap());
|
||||
auto* gced =
|
||||
MakeGarbageCollected<GCedWithCustomWeakCallback>(GetAllocationHandle());
|
||||
WeakCallbackDispatcher::Setup(gced);
|
||||
EXPECT_EQ(0u, WeakCallbackDispatcher::callback_callcount);
|
||||
gced->Trace(&visitor);
|
||||
@ -250,7 +256,7 @@ class GCedWithComposite final : public GarbageCollected<GCedWithComposite> {
|
||||
|
||||
TEST_F(VisitorTest, DispatchToCompositeObject) {
|
||||
Member<GCedWithComposite> ref =
|
||||
MakeGarbageCollected<GCedWithComposite>(GetHeap());
|
||||
MakeGarbageCollected<GCedWithComposite>(GetAllocationHandle());
|
||||
DispatchingVisitor visitor(ref, ref);
|
||||
EXPECT_EQ(0u, Composite::callback_callcount);
|
||||
visitor.Trace(ref);
|
||||
|
@ -170,8 +170,8 @@ TEST_F(WriteBarrierTest, EnableDisableIncrementalMarking) {
|
||||
}
|
||||
|
||||
TEST_F(WriteBarrierTest, TriggersWhenMarkingIsOn) {
|
||||
auto* object1 = MakeGarbageCollected<GCed>(GetHeap());
|
||||
auto* object2 = MakeGarbageCollected<GCed>(GetHeap());
|
||||
auto* object1 = MakeGarbageCollected<GCed>(GetAllocationHandle());
|
||||
auto* object2 = MakeGarbageCollected<GCed>(GetAllocationHandle());
|
||||
{
|
||||
ExpectWriteBarrierFires scope(marker(), {object1});
|
||||
EXPECT_FALSE(object1->IsMarked());
|
||||
@ -181,16 +181,16 @@ TEST_F(WriteBarrierTest, TriggersWhenMarkingIsOn) {
|
||||
}
|
||||
|
||||
TEST_F(WriteBarrierTest, BailoutWhenMarkingIsOff) {
|
||||
auto* object1 = MakeGarbageCollected<GCed>(GetHeap());
|
||||
auto* object2 = MakeGarbageCollected<GCed>(GetHeap());
|
||||
auto* object1 = MakeGarbageCollected<GCed>(GetAllocationHandle());
|
||||
auto* object2 = MakeGarbageCollected<GCed>(GetAllocationHandle());
|
||||
EXPECT_FALSE(object1->IsMarked());
|
||||
object2->set_next(object1);
|
||||
EXPECT_FALSE(object1->IsMarked());
|
||||
}
|
||||
|
||||
TEST_F(WriteBarrierTest, BailoutIfMarked) {
|
||||
auto* object1 = MakeGarbageCollected<GCed>(GetHeap());
|
||||
auto* object2 = MakeGarbageCollected<GCed>(GetHeap());
|
||||
auto* object1 = MakeGarbageCollected<GCed>(GetAllocationHandle());
|
||||
auto* object2 = MakeGarbageCollected<GCed>(GetAllocationHandle());
|
||||
EXPECT_TRUE(HeapObjectHeader::FromPayload(object1).TryMarkAtomic());
|
||||
{
|
||||
ExpectNoWriteBarrierFires scope(marker(), {object1});
|
||||
@ -199,18 +199,18 @@ TEST_F(WriteBarrierTest, BailoutIfMarked) {
|
||||
}
|
||||
|
||||
TEST_F(WriteBarrierTest, MemberInitializingStoreNoBarrier) {
|
||||
auto* object1 = MakeGarbageCollected<GCed>(GetHeap());
|
||||
auto* object1 = MakeGarbageCollected<GCed>(GetAllocationHandle());
|
||||
{
|
||||
ExpectNoWriteBarrierFires scope(marker(), {object1});
|
||||
auto* object2 = MakeGarbageCollected<GCed>(GetHeap(), object1);
|
||||
auto* object2 = MakeGarbageCollected<GCed>(GetAllocationHandle(), object1);
|
||||
HeapObjectHeader& object2_header = HeapObjectHeader::FromPayload(object2);
|
||||
EXPECT_FALSE(object2_header.IsMarked());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(WriteBarrierTest, MemberReferenceAssignMember) {
|
||||
auto* obj = MakeGarbageCollected<GCed>(GetHeap());
|
||||
auto* ref_obj = MakeGarbageCollected<GCed>(GetHeap());
|
||||
auto* obj = MakeGarbageCollected<GCed>(GetAllocationHandle());
|
||||
auto* ref_obj = MakeGarbageCollected<GCed>(GetAllocationHandle());
|
||||
Member<GCed>& m2 = ref_obj->next_ref();
|
||||
Member<GCed> m3(obj);
|
||||
{
|
||||
@ -220,7 +220,7 @@ TEST_F(WriteBarrierTest, MemberReferenceAssignMember) {
|
||||
}
|
||||
|
||||
TEST_F(WriteBarrierTest, MemberSetSentinelValueNoBarrier) {
|
||||
auto* obj = MakeGarbageCollected<GCed>(GetHeap());
|
||||
auto* obj = MakeGarbageCollected<GCed>(GetAllocationHandle());
|
||||
Member<GCed>& m = obj->next_ref();
|
||||
{
|
||||
ExpectNoWriteBarrierFires scope(marker(), {});
|
||||
@ -229,12 +229,12 @@ TEST_F(WriteBarrierTest, MemberSetSentinelValueNoBarrier) {
|
||||
}
|
||||
|
||||
TEST_F(WriteBarrierTest, MemberCopySentinelValueNoBarrier) {
|
||||
auto* obj1 = MakeGarbageCollected<GCed>(GetHeap());
|
||||
auto* obj1 = MakeGarbageCollected<GCed>(GetAllocationHandle());
|
||||
Member<GCed>& m1 = obj1->next_ref();
|
||||
m1 = kSentinelPointer;
|
||||
{
|
||||
ExpectNoWriteBarrierFires scope(marker(), {});
|
||||
auto* obj2 = MakeGarbageCollected<GCed>(GetHeap());
|
||||
auto* obj2 = MakeGarbageCollected<GCed>(GetAllocationHandle());
|
||||
obj2->next_ref() = m1;
|
||||
}
|
||||
}
|
||||
@ -291,8 +291,8 @@ class ParentWithMixinPointer : public GarbageCollected<ParentWithMixinPointer> {
|
||||
|
||||
TEST_F(WriteBarrierTest, WriteBarrierOnUnmarkedMixinApplication) {
|
||||
ParentWithMixinPointer* parent =
|
||||
MakeGarbageCollected<ParentWithMixinPointer>(GetHeap());
|
||||
auto* child = MakeGarbageCollected<Child>(GetHeap());
|
||||
MakeGarbageCollected<ParentWithMixinPointer>(GetAllocationHandle());
|
||||
auto* child = MakeGarbageCollected<Child>(GetAllocationHandle());
|
||||
Mixin* mixin = static_cast<Mixin*>(child);
|
||||
EXPECT_NE(static_cast<void*>(child), static_cast<void*>(mixin));
|
||||
{
|
||||
@ -303,8 +303,8 @@ TEST_F(WriteBarrierTest, WriteBarrierOnUnmarkedMixinApplication) {
|
||||
|
||||
TEST_F(WriteBarrierTest, NoWriteBarrierOnMarkedMixinApplication) {
|
||||
ParentWithMixinPointer* parent =
|
||||
MakeGarbageCollected<ParentWithMixinPointer>(GetHeap());
|
||||
auto* child = MakeGarbageCollected<Child>(GetHeap());
|
||||
MakeGarbageCollected<ParentWithMixinPointer>(GetAllocationHandle());
|
||||
auto* child = MakeGarbageCollected<Child>(GetAllocationHandle());
|
||||
EXPECT_TRUE(HeapObjectHeader::FromPayload(child).TryMarkAtomic());
|
||||
Mixin* mixin = static_cast<Mixin*>(child);
|
||||
EXPECT_NE(static_cast<void*>(child), static_cast<void*>(mixin));
|
||||
|
Loading…
Reference in New Issue
Block a user