1*3ac0a46fSAndroid Build Coastguard Worker // Copyright 2020 The PDFium Authors
2*3ac0a46fSAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*3ac0a46fSAndroid Build Coastguard Worker // found in the LICENSE file.
4*3ac0a46fSAndroid Build Coastguard Worker
5*3ac0a46fSAndroid Build Coastguard Worker #include "fxjs/gc/heap.h"
6*3ac0a46fSAndroid Build Coastguard Worker
7*3ac0a46fSAndroid Build Coastguard Worker #include <memory>
8*3ac0a46fSAndroid Build Coastguard Worker #include <set>
9*3ac0a46fSAndroid Build Coastguard Worker
10*3ac0a46fSAndroid Build Coastguard Worker #include "testing/fxgc_unittest.h"
11*3ac0a46fSAndroid Build Coastguard Worker #include "testing/gtest/include/gtest/gtest.h"
12*3ac0a46fSAndroid Build Coastguard Worker #include "testing/v8_test_environment.h"
13*3ac0a46fSAndroid Build Coastguard Worker #include "third_party/base/containers/contains.h"
14*3ac0a46fSAndroid Build Coastguard Worker #include "v8/include/cppgc/allocation.h"
15*3ac0a46fSAndroid Build Coastguard Worker #include "v8/include/cppgc/persistent.h"
16*3ac0a46fSAndroid Build Coastguard Worker
17*3ac0a46fSAndroid Build Coastguard Worker namespace {
18*3ac0a46fSAndroid Build Coastguard Worker
19*3ac0a46fSAndroid Build Coastguard Worker class PseudoCollectible : public cppgc::GarbageCollected<PseudoCollectible> {
20*3ac0a46fSAndroid Build Coastguard Worker public:
ClearCounts()21*3ac0a46fSAndroid Build Coastguard Worker static void ClearCounts() {
22*3ac0a46fSAndroid Build Coastguard Worker s_live_.clear();
23*3ac0a46fSAndroid Build Coastguard Worker s_dead_.clear();
24*3ac0a46fSAndroid Build Coastguard Worker }
LiveCount()25*3ac0a46fSAndroid Build Coastguard Worker static size_t LiveCount() { return s_live_.size(); }
DeadCount()26*3ac0a46fSAndroid Build Coastguard Worker static size_t DeadCount() { return s_dead_.size(); }
27*3ac0a46fSAndroid Build Coastguard Worker
PseudoCollectible()28*3ac0a46fSAndroid Build Coastguard Worker PseudoCollectible() { s_live_.insert(this); }
~PseudoCollectible()29*3ac0a46fSAndroid Build Coastguard Worker virtual ~PseudoCollectible() {
30*3ac0a46fSAndroid Build Coastguard Worker s_live_.erase(this);
31*3ac0a46fSAndroid Build Coastguard Worker s_dead_.insert(this);
32*3ac0a46fSAndroid Build Coastguard Worker }
33*3ac0a46fSAndroid Build Coastguard Worker
IsLive() const34*3ac0a46fSAndroid Build Coastguard Worker bool IsLive() const { return pdfium::Contains(s_live_, this); }
35*3ac0a46fSAndroid Build Coastguard Worker
Trace(cppgc::Visitor * visitor) const36*3ac0a46fSAndroid Build Coastguard Worker virtual void Trace(cppgc::Visitor* visitor) const {}
37*3ac0a46fSAndroid Build Coastguard Worker
38*3ac0a46fSAndroid Build Coastguard Worker private:
39*3ac0a46fSAndroid Build Coastguard Worker static std::set<const PseudoCollectible*> s_live_;
40*3ac0a46fSAndroid Build Coastguard Worker static std::set<const PseudoCollectible*> s_dead_;
41*3ac0a46fSAndroid Build Coastguard Worker };
42*3ac0a46fSAndroid Build Coastguard Worker
43*3ac0a46fSAndroid Build Coastguard Worker std::set<const PseudoCollectible*> PseudoCollectible::s_live_;
44*3ac0a46fSAndroid Build Coastguard Worker std::set<const PseudoCollectible*> PseudoCollectible::s_dead_;
45*3ac0a46fSAndroid Build Coastguard Worker
46*3ac0a46fSAndroid Build Coastguard Worker class CollectibleHolder {
47*3ac0a46fSAndroid Build Coastguard Worker public:
CollectibleHolder(PseudoCollectible * holdee)48*3ac0a46fSAndroid Build Coastguard Worker explicit CollectibleHolder(PseudoCollectible* holdee) : holdee_(holdee) {}
49*3ac0a46fSAndroid Build Coastguard Worker ~CollectibleHolder() = default;
50*3ac0a46fSAndroid Build Coastguard Worker
holdee() const51*3ac0a46fSAndroid Build Coastguard Worker PseudoCollectible* holdee() const { return holdee_; }
52*3ac0a46fSAndroid Build Coastguard Worker
53*3ac0a46fSAndroid Build Coastguard Worker private:
54*3ac0a46fSAndroid Build Coastguard Worker cppgc::Persistent<PseudoCollectible> holdee_;
55*3ac0a46fSAndroid Build Coastguard Worker };
56*3ac0a46fSAndroid Build Coastguard Worker
57*3ac0a46fSAndroid Build Coastguard Worker class Bloater : public cppgc::GarbageCollected<Bloater> {
58*3ac0a46fSAndroid Build Coastguard Worker public:
Trace(cppgc::Visitor * visitor) const59*3ac0a46fSAndroid Build Coastguard Worker void Trace(cppgc::Visitor* visitor) const {}
60*3ac0a46fSAndroid Build Coastguard Worker uint8_t bloat_[65536];
61*3ac0a46fSAndroid Build Coastguard Worker };
62*3ac0a46fSAndroid Build Coastguard Worker
63*3ac0a46fSAndroid Build Coastguard Worker } // namespace
64*3ac0a46fSAndroid Build Coastguard Worker
65*3ac0a46fSAndroid Build Coastguard Worker class HeapUnitTest : public FXGCUnitTest {
66*3ac0a46fSAndroid Build Coastguard Worker public:
67*3ac0a46fSAndroid Build Coastguard Worker HeapUnitTest() = default;
68*3ac0a46fSAndroid Build Coastguard Worker ~HeapUnitTest() override = default;
69*3ac0a46fSAndroid Build Coastguard Worker
70*3ac0a46fSAndroid Build Coastguard Worker // FXGCUnitTest:
TearDown()71*3ac0a46fSAndroid Build Coastguard Worker void TearDown() override {
72*3ac0a46fSAndroid Build Coastguard Worker PseudoCollectible::ClearCounts();
73*3ac0a46fSAndroid Build Coastguard Worker FXGCUnitTest::TearDown();
74*3ac0a46fSAndroid Build Coastguard Worker }
75*3ac0a46fSAndroid Build Coastguard Worker };
76*3ac0a46fSAndroid Build Coastguard Worker
TEST_F(HeapUnitTest,SeveralHeaps)77*3ac0a46fSAndroid Build Coastguard Worker TEST_F(HeapUnitTest, SeveralHeaps) {
78*3ac0a46fSAndroid Build Coastguard Worker FXGCScopedHeap heap1 = FXGC_CreateHeap();
79*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(heap1);
80*3ac0a46fSAndroid Build Coastguard Worker
81*3ac0a46fSAndroid Build Coastguard Worker FXGCScopedHeap heap2 = FXGC_CreateHeap();
82*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(heap2);
83*3ac0a46fSAndroid Build Coastguard Worker
84*3ac0a46fSAndroid Build Coastguard Worker FXGCScopedHeap heap3 = FXGC_CreateHeap();
85*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(heap3);
86*3ac0a46fSAndroid Build Coastguard Worker
87*3ac0a46fSAndroid Build Coastguard Worker // Test manually destroying the heap.
88*3ac0a46fSAndroid Build Coastguard Worker heap3.reset();
89*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(heap3);
90*3ac0a46fSAndroid Build Coastguard Worker heap3.reset();
91*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(heap3);
92*3ac0a46fSAndroid Build Coastguard Worker }
93*3ac0a46fSAndroid Build Coastguard Worker
TEST_F(HeapUnitTest,NoReferences)94*3ac0a46fSAndroid Build Coastguard Worker TEST_F(HeapUnitTest, NoReferences) {
95*3ac0a46fSAndroid Build Coastguard Worker FXGCScopedHeap heap1 = FXGC_CreateHeap();
96*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(heap1);
97*3ac0a46fSAndroid Build Coastguard Worker {
98*3ac0a46fSAndroid Build Coastguard Worker auto holder = std::make_unique<CollectibleHolder>(
99*3ac0a46fSAndroid Build Coastguard Worker cppgc::MakeGarbageCollected<PseudoCollectible>(
100*3ac0a46fSAndroid Build Coastguard Worker heap1->GetAllocationHandle()));
101*3ac0a46fSAndroid Build Coastguard Worker
102*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(holder->holdee()->IsLive());
103*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(1u, PseudoCollectible::LiveCount());
104*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(0u, PseudoCollectible::DeadCount());
105*3ac0a46fSAndroid Build Coastguard Worker }
106*3ac0a46fSAndroid Build Coastguard Worker FXGC_ForceGarbageCollection(heap1.get());
107*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(0u, PseudoCollectible::LiveCount());
108*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(1u, PseudoCollectible::DeadCount());
109*3ac0a46fSAndroid Build Coastguard Worker }
110*3ac0a46fSAndroid Build Coastguard Worker
TEST_F(HeapUnitTest,HasReferences)111*3ac0a46fSAndroid Build Coastguard Worker TEST_F(HeapUnitTest, HasReferences) {
112*3ac0a46fSAndroid Build Coastguard Worker FXGCScopedHeap heap1 = FXGC_CreateHeap();
113*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(heap1);
114*3ac0a46fSAndroid Build Coastguard Worker {
115*3ac0a46fSAndroid Build Coastguard Worker auto holder = std::make_unique<CollectibleHolder>(
116*3ac0a46fSAndroid Build Coastguard Worker cppgc::MakeGarbageCollected<PseudoCollectible>(
117*3ac0a46fSAndroid Build Coastguard Worker heap1->GetAllocationHandle()));
118*3ac0a46fSAndroid Build Coastguard Worker
119*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(holder->holdee()->IsLive());
120*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(1u, PseudoCollectible::LiveCount());
121*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(0u, PseudoCollectible::DeadCount());
122*3ac0a46fSAndroid Build Coastguard Worker
123*3ac0a46fSAndroid Build Coastguard Worker FXGC_ForceGarbageCollection(heap1.get());
124*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(holder->holdee()->IsLive());
125*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(1u, PseudoCollectible::LiveCount());
126*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(0u, PseudoCollectible::DeadCount());
127*3ac0a46fSAndroid Build Coastguard Worker }
128*3ac0a46fSAndroid Build Coastguard Worker }
129*3ac0a46fSAndroid Build Coastguard Worker
130*3ac0a46fSAndroid Build Coastguard Worker // TODO(tsepez): enable when CPPGC fixes this segv.
TEST_F(HeapUnitTest,DISABLED_DeleteHeapHasReferences)131*3ac0a46fSAndroid Build Coastguard Worker TEST_F(HeapUnitTest, DISABLED_DeleteHeapHasReferences) {
132*3ac0a46fSAndroid Build Coastguard Worker FXGCScopedHeap heap1 = FXGC_CreateHeap();
133*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(heap1);
134*3ac0a46fSAndroid Build Coastguard Worker {
135*3ac0a46fSAndroid Build Coastguard Worker auto holder = std::make_unique<CollectibleHolder>(
136*3ac0a46fSAndroid Build Coastguard Worker cppgc::MakeGarbageCollected<PseudoCollectible>(
137*3ac0a46fSAndroid Build Coastguard Worker heap1->GetAllocationHandle()));
138*3ac0a46fSAndroid Build Coastguard Worker
139*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(holder->holdee()->IsLive());
140*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(1u, PseudoCollectible::LiveCount());
141*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(0u, PseudoCollectible::DeadCount());
142*3ac0a46fSAndroid Build Coastguard Worker
143*3ac0a46fSAndroid Build Coastguard Worker heap1.reset();
144*3ac0a46fSAndroid Build Coastguard Worker
145*3ac0a46fSAndroid Build Coastguard Worker // Maybe someday magically nulled by heap destruction.
146*3ac0a46fSAndroid Build Coastguard Worker EXPECT_FALSE(holder->holdee());
147*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(1u, PseudoCollectible::LiveCount());
148*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(0u, PseudoCollectible::DeadCount());
149*3ac0a46fSAndroid Build Coastguard Worker }
150*3ac0a46fSAndroid Build Coastguard Worker }
151*3ac0a46fSAndroid Build Coastguard Worker
TEST_F(HeapUnitTest,DeleteHeapNoReferences)152*3ac0a46fSAndroid Build Coastguard Worker TEST_F(HeapUnitTest, DeleteHeapNoReferences) {
153*3ac0a46fSAndroid Build Coastguard Worker FXGCScopedHeap heap1 = FXGC_CreateHeap();
154*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(heap1);
155*3ac0a46fSAndroid Build Coastguard Worker {
156*3ac0a46fSAndroid Build Coastguard Worker auto holder = std::make_unique<CollectibleHolder>(
157*3ac0a46fSAndroid Build Coastguard Worker cppgc::MakeGarbageCollected<PseudoCollectible>(
158*3ac0a46fSAndroid Build Coastguard Worker heap1->GetAllocationHandle()));
159*3ac0a46fSAndroid Build Coastguard Worker
160*3ac0a46fSAndroid Build Coastguard Worker EXPECT_TRUE(holder->holdee()->IsLive());
161*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(1u, PseudoCollectible::LiveCount());
162*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(0u, PseudoCollectible::DeadCount());
163*3ac0a46fSAndroid Build Coastguard Worker }
164*3ac0a46fSAndroid Build Coastguard Worker heap1.reset();
165*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(0u, PseudoCollectible::LiveCount());
166*3ac0a46fSAndroid Build Coastguard Worker EXPECT_EQ(1u, PseudoCollectible::DeadCount());
167*3ac0a46fSAndroid Build Coastguard Worker }
168*3ac0a46fSAndroid Build Coastguard Worker
TEST_F(HeapUnitTest,Bloat)169*3ac0a46fSAndroid Build Coastguard Worker TEST_F(HeapUnitTest, Bloat) {
170*3ac0a46fSAndroid Build Coastguard Worker ASSERT_TRUE(heap());
171*3ac0a46fSAndroid Build Coastguard Worker for (int i = 0; i < 100000; ++i) {
172*3ac0a46fSAndroid Build Coastguard Worker cppgc::MakeGarbageCollected<Bloater>(heap()->GetAllocationHandle());
173*3ac0a46fSAndroid Build Coastguard Worker Pump(); // Do not force GC, must happen implicitly when space required.
174*3ac0a46fSAndroid Build Coastguard Worker }
175*3ac0a46fSAndroid Build Coastguard Worker }
176