Commit 81b74a0f authored by Omer Katz's avatar Omer Katz Committed by Commit Bot

cppgc: First batch of unittest from heap_test.cc

Migrating unittests from Blink that were not already covered by cppgc.

Bug: chromium:1056170
Change-Id: If31591c3f1e99562028087c2b818f5ceb8122ec9
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2821542
Commit-Queue: Omer Katz <omerkatz@chromium.org>
Reviewed-by: 's avatarMichael Lippautz <mlippautz@chromium.org>
Cr-Commit-Position: refs/heads/master@{#73960}
parent f9506988
......@@ -35,13 +35,10 @@ class ObjectSizeCounter : private HeapVisitor<ObjectSizeCounter> {
private:
static size_t ObjectSize(const HeapObjectHeader* header) {
const size_t size =
header->IsLargeObject()
? static_cast<const LargePage*>(BasePage::FromPayload(header))
->PayloadSize()
: header->GetSize();
DCHECK_GE(size, sizeof(HeapObjectHeader));
return size - sizeof(HeapObjectHeader);
return header->IsLargeObject()
? static_cast<const LargePage*>(BasePage::FromPayload(header))
->ObjectSize()
: header->ObjectSize();
}
bool VisitHeapObjectHeader(HeapObjectHeader* header) {
......
......@@ -219,6 +219,7 @@ void HeapObjectHeader::SetSize(size_t size) {
template <AccessMode mode>
size_t HeapObjectHeader::ObjectSize() const {
DCHECK_GT(GetSize<mode>(), sizeof(HeapObjectHeader));
return GetSize<mode>() - sizeof(HeapObjectHeader);
}
......
......@@ -210,7 +210,10 @@ class V8_EXPORT_PRIVATE LargePage final : public BasePage {
ConstAddress PayloadEnd() const;
size_t PayloadSize() const { return payload_size_; }
size_t ObjectSize() const { return payload_size_ - sizeof(HeapObjectHeader); }
size_t ObjectSize() const {
DCHECK_GT(payload_size_, sizeof(HeapObjectHeader));
return payload_size_ - sizeof(HeapObjectHeader);
}
bool PayloadContains(ConstAddress address) const {
return (PayloadStart() <= address) && (address < PayloadEnd());
......
......@@ -86,6 +86,7 @@ v8_source_set("cppgc_unittests_sources") {
testonly = true
sources = [
"heap/cppgc/allocation-unittest.cc",
"heap/cppgc/compactor-unittest.cc",
"heap/cppgc/concurrent-marking-unittest.cc",
"heap/cppgc/concurrent-sweeper-unittest.cc",
......
// Copyright 2021 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 "test/unittests/heap/cppgc/tests.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace cppgc {
namespace internal {
namespace {
class CppgcAllocationTest : public testing::TestWithHeap {};
struct GCed final : GarbageCollected<GCed> {
void Trace(cppgc::Visitor*) const {}
};
class HeapAllocatedArray final : public GarbageCollected<HeapAllocatedArray> {
public:
HeapAllocatedArray() {
for (int i = 0; i < kArraySize; ++i) {
array_[i] = i % 128;
}
}
int8_t at(size_t i) { return array_[i]; }
void Trace(Visitor* visitor) const {}
private:
static const int kArraySize = 1000;
int8_t array_[kArraySize];
};
} // namespace
TEST_F(CppgcAllocationTest, MakeGarbageCollectedPreservesPayload) {
// Allocate an object in the heap.
HeapAllocatedArray* array =
MakeGarbageCollected<HeapAllocatedArray>(GetAllocationHandle());
// Sanity check of the contents in the heap.
EXPECT_EQ(0, array->at(0));
EXPECT_EQ(42, array->at(42));
EXPECT_EQ(0, array->at(128));
EXPECT_EQ(999 % 128, array->at(999));
}
TEST_F(CppgcAllocationTest, ReuseMemoryFromFreelist) {
// Allocate 3 objects so that the address we look for below is not at the
// start of the page.
MakeGarbageCollected<GCed>(GetAllocationHandle());
MakeGarbageCollected<GCed>(GetAllocationHandle());
GCed* p1 = MakeGarbageCollected<GCed>(GetAllocationHandle());
// GC reclaims all objects. LABs are reset during the GC.
PreciseGC();
// Now the freed memory in the first GC should be reused. Allocating 3
// objects again should suffice but allocating 5 to give the test some slack.
bool reused_memory_found = false;
for (int i = 0; i < 5; i++) {
GCed* p2 = MakeGarbageCollected<GCed>(GetAllocationHandle());
if (p1 == p2) {
reused_memory_found = true;
break;
}
}
EXPECT_TRUE(reused_memory_found);
}
} // namespace internal
} // namespace cppgc
......@@ -114,6 +114,18 @@ TEST_F(TestWithHeapWithCustomSpaces, AllocateOnCustomSpaces) {
NormalPage::FromPayload(regular)->space()->index());
}
TEST_F(TestWithHeapWithCustomSpaces, DifferentSpacesUsesDifferentPages) {
auto* regular =
MakeGarbageCollected<RegularGCed>(GetHeap()->GetAllocationHandle());
auto* custom1 =
MakeGarbageCollected<CustomGCed1>(GetHeap()->GetAllocationHandle());
auto* custom2 =
MakeGarbageCollected<CustomGCed2>(GetHeap()->GetAllocationHandle());
EXPECT_NE(NormalPage::FromPayload(regular), NormalPage::FromPayload(custom1));
EXPECT_NE(NormalPage::FromPayload(regular), NormalPage::FromPayload(custom2));
EXPECT_NE(NormalPage::FromPayload(custom1), NormalPage::FromPayload(custom2));
}
TEST_F(TestWithHeapWithCustomSpaces,
AllocateOnCustomSpacesSpecifiedThroughBase) {
auto* regular =
......
......@@ -322,5 +322,16 @@ TEST_F(GCHeapDeathTest, LargeChainOfNewStates) {
EXPECT_DEATH_IF_SUPPORTED(Heap::From(GetHeap())->Terminate(), "");
}
TEST_F(GCHeapTest, IsHeapObjectAliveForConstPointer) {
// Regression test: http://crbug.com/661363.
GCed<64>* object = MakeGarbageCollected<GCed<64>>(GetAllocationHandle());
HeapObjectHeader& header = HeapObjectHeader::FromPayload(object);
LivenessBroker broker = internal::LivenessBrokerFactory::Create();
EXPECT_TRUE(header.TryMarkAtomic());
EXPECT_TRUE(broker.IsHeapObjectAlive(object));
const GCed<64>* const_object = const_cast<const GCed<64>*>(object);
EXPECT_TRUE(broker.IsHeapObjectAlive(const_object));
}
} // namespace internal
} // namespace cppgc
......@@ -123,7 +123,7 @@ struct Holder : public GarbageCollected<Holder<T>> {
} // namespace
TEST_F(MarkingVerifierTest, DoesntDieOnInConstructionObjectWithWriteBarrier) {
// Regression test: https://crbug.com/v8/10989.
// Regression test: https://crbug.com/v8/10989.
// GCedWithCallbackAndChild is marked by write barrier and then discarded by
// FlushNotFullyConstructedObjects because it is already marked.
Persistent<Holder<GCedWithCallbackAndChild>> persistent =
......
......@@ -12,6 +12,7 @@
#include "include/cppgc/persistent.h"
#include "include/cppgc/source-location.h"
#include "include/cppgc/type-traits.h"
#include "src/base/logging.h"
#include "src/heap/cppgc/heap.h"
#include "src/heap/cppgc/liveness-broker.h"
#include "src/heap/cppgc/visitor.h"
......@@ -108,7 +109,7 @@ class RootVisitor final : public VisitorBase {
std::vector<std::pair<WeakCallback, const void*>> weak_callbacks_;
};
class PersistentTest : public testing::TestSupportingAllocationOnly {};
class PersistentTest : public testing::TestWithHeap {};
} // namespace
......@@ -928,5 +929,71 @@ TEST_F(PersistentTest, Lock) {
auto strong = weak.Lock();
}
namespace {
class TraceCounter final : public GarbageCollected<TraceCounter> {
public:
TraceCounter() : nested_(nullptr) {}
explicit TraceCounter(TraceCounter* nested) : nested_(nested) {}
void Trace(cppgc::Visitor* visitor) const {
visitor->Trace(nested_);
trace_calls_++;
}
TraceCounter* nested() const { return nested_; }
size_t trace_calls() const { return trace_calls_; }
private:
Member<TraceCounter> nested_;
mutable size_t trace_calls_ = 0;
};
class DestructionCounter final : public GarbageCollected<DestructionCounter> {
public:
static size_t destructor_calls_;
~DestructionCounter() { destructor_calls_++; }
void Trace(cppgc::Visitor*) const {}
};
size_t DestructionCounter::destructor_calls_;
} // namespace
TEST_F(PersistentTest, PersistentRetainsObject) {
Persistent<TraceCounter> trace_counter =
MakeGarbageCollected<TraceCounter>(GetAllocationHandle());
EXPECT_EQ(0u, trace_counter->trace_calls());
PreciseGC();
size_t saved_trace_count = trace_counter->trace_calls();
EXPECT_LT(0u, saved_trace_count);
Persistent<TraceCounter> class_with_member =
MakeGarbageCollected<TraceCounter>(
GetAllocationHandle(),
MakeGarbageCollected<TraceCounter>(GetAllocationHandle()));
EXPECT_EQ(0u, class_with_member->nested()->trace_calls());
PreciseGC();
EXPECT_LT(0u, class_with_member->nested()->trace_calls());
EXPECT_LT(saved_trace_count, trace_counter->trace_calls());
USE(trace_counter);
USE(class_with_member);
}
TEST_F(PersistentTest, ObjectReclaimedAfterClearedPersistent) {
{
DestructionCounter::destructor_calls_ = 0;
Persistent<DestructionCounter> finalized =
MakeGarbageCollected<DestructionCounter>(GetAllocationHandle());
EXPECT_EQ(0u, DestructionCounter::destructor_calls_);
PreciseGC();
EXPECT_EQ(0u, DestructionCounter::destructor_calls_);
USE(finalized);
}
PreciseGC();
EXPECT_EQ(1u, DestructionCounter::destructor_calls_);
}
} // namespace internal
} // namespace cppgc
......@@ -326,5 +326,24 @@ TEST_F(SweeperTest, LazySweepingDuringAllocation) {
EXPECT_NE(new_object1, new_object2);
}
TEST_F(SweeperTest, LazySweepingNormalPages) {
using GCedObject = GCed<sizeof(size_t)>;
EXPECT_EQ(0u, g_destructor_callcount);
PreciseGC();
EXPECT_EQ(0u, g_destructor_callcount);
MakeGarbageCollected<GCedObject>(GetAllocationHandle());
static constexpr Heap::Config config = {
Heap::Config::CollectionType::kMajor,
Heap::Config::StackState::kNoHeapPointers,
Heap::Config::MarkingType::kAtomic,
Heap::Config::SweepingType::kIncrementalAndConcurrent};
Heap::From(GetHeap())->CollectGarbage(config);
EXPECT_EQ(0u, g_destructor_callcount);
MakeGarbageCollected<GCedObject>(GetAllocationHandle());
EXPECT_EQ(1u, g_destructor_callcount);
PreciseGC();
EXPECT_EQ(2u, g_destructor_callcount);
}
} // namespace internal
} // namespace cppgc
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment