xref: /aosp_15_r20/external/pdfium/fxjs/gc/heap_unittest.cpp (revision 3ac0a46f773bac49fa9476ec2b1cf3f8da5ec3a4)
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