1 /*
2 * Copyright (c) 2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "common_components/heap/collector/marking_collector.h"
17 #include "common_components/heap/heap_manager.h"
18 #include "common_components/heap/ark_collector/ark_collector.h"
19 #include "common_components/mutator/mutator_manager.h"
20 #include "common_components/tests/test_helper.h"
21 #include <cstdint>
22
23 using namespace common;
24
25 namespace common::test {
26 class MarkingCollectorTest : public common::test::BaseTestWithScope {
27 protected:
SetUpTestCase()28 static void SetUpTestCase()
29 {
30 BaseRuntime::GetInstance()->Init();
31 }
32
TearDownTestCase()33 static void TearDownTestCase()
34 {
35 BaseRuntime::GetInstance()->Fini();
36 }
SetUp()37 void SetUp() override
38 {
39 MutatorManager::Instance().CreateRuntimeMutator(ThreadType::ARK_PROCESSOR);
40 }
41
TearDown()42 void TearDown() override
43 {
44 MutatorManager::Instance().DestroyRuntimeMutator(ThreadType::ARK_PROCESSOR);
45 }
46
47 StaticRootTable rootTable_;
ContainsRoot(StaticRootTable & table,const StaticRootTable::StaticRootArray * array,uint32_t size)48 bool ContainsRoot(StaticRootTable& table, const StaticRootTable::StaticRootArray* array, uint32_t size)
49 {
50 bool found = false;
51 auto visitor = [&found, array, size](RefField<>& root) {
52 for (uint32_t i = 0; i < size; ++i) {
53 if (&root == array->content[i]) {
54 found = true;
55 return;
56 }
57 }
58 };
59 table.VisitRoots(visitor);
60 return found;
61 }
62 class TableMarkingCollctor : public MarkingCollector {
63 public:
64 using MarkingCollector::SetGCReason;
65 using MarkingCollector::MarkingRoots;
66 using MarkingCollector::PushRootToWorkStack;
67 using MarkingCollector::UpdateNativeThreshold;
68 };
69 };
70
HWTEST_F_L0(MarkingCollectorTest,RunGarbageCollection)71 HWTEST_F_L0(MarkingCollectorTest, RunGarbageCollection)
72 {
73 MarkingCollector& collector = reinterpret_cast<MarkingCollector&>(Heap::GetHeap().GetCollector());
74 Heap::GetHeap().SetGCReason(GCReason::GC_REASON_YOUNG);
75 collector.RunGarbageCollection(0, GCReason::GC_REASON_USER, common::GC_TYPE_FULL);
76 ASSERT_FALSE(Heap::GetHeap().GetCollector().GetGCStats().isYoungGC());
77
78 Heap::GetHeap().SetGCReason(GCReason::GC_REASON_BACKUP);
79 collector.RunGarbageCollection(0, GCReason::GC_REASON_OOM, common::GC_TYPE_FULL);
80 ASSERT_FALSE(Heap::GetHeap().GetCollector().GetGCStats().isYoungGC());
81 }
82
HWTEST_F_L0(MarkingCollectorTest,RunGarbageCollectionTest2)83 HWTEST_F_L0(MarkingCollectorTest, RunGarbageCollectionTest2)
84 {
85 MarkingCollector& collector = reinterpret_cast<MarkingCollector&>(Heap::GetHeap().GetCollector());
86 Heap::GetHeap().SetGCReason(GCReason::GC_REASON_YOUNG);
87 collector.RunGarbageCollection(0, GCReason::GC_REASON_YOUNG, common::GC_TYPE_FULL);
88 ASSERT_TRUE(Heap::GetHeap().GetCollector().GetGCStats().isYoungGC());
89 }
90
HWTEST_F_L0(MarkingCollectorTest,UpdateNativeThresholdTest)91 HWTEST_F_L0(MarkingCollectorTest, UpdateNativeThresholdTest)
92 {
93 TableMarkingCollctor& collector = reinterpret_cast<TableMarkingCollctor&>(Heap::GetHeap().GetCollector());
94 GCParam gcParam;
95 gcParam.minGrowBytes = 1024;
96 Heap::GetHeap().SetNativeHeapThreshold(512);
97 auto oldThreshold = Heap::GetHeap().GetNativeHeapThreshold();
98 collector.UpdateNativeThreshold(gcParam);
99 auto newThreshold = Heap::GetHeap().GetNativeHeapThreshold();
100 EXPECT_NE(newThreshold, oldThreshold);
101 }
102
HWTEST_F_L0(MarkingCollectorTest,UpdateNativeThresholdTest2)103 HWTEST_F_L0(MarkingCollectorTest, UpdateNativeThresholdTest2)
104 {
105 TableMarkingCollctor& collector = reinterpret_cast<TableMarkingCollctor&>(Heap::GetHeap().GetCollector());
106 Heap::GetHeap().NotifyNativeAllocation(1100 * MB);
107
108 GCParam param;
109 collector.UpdateNativeThreshold(param);
110 ASSERT_TRUE(Heap::GetHeap().GetNotifiedNativeSize() > MAX_NATIVE_SIZE_INC);
111 }
112
HWTEST_F_L0(MarkingCollectorTest,MarkingRootsTest)113 HWTEST_F_L0(MarkingCollectorTest, MarkingRootsTest)
114 {
115 TableMarkingCollctor& collector = reinterpret_cast<TableMarkingCollctor&>(Heap::GetHeap().GetCollector());
116 CArrayList<BaseObject *> roots;
117 RegionSpace& theAllocator = reinterpret_cast<RegionSpace&>(Heap::GetHeap().GetAllocator());
118 uintptr_t addr = theAllocator.AllocOldRegion();
119 ASSERT_NE(addr, 0);
120 BaseObject* obj = reinterpret_cast<BaseObject*>(addr);
121 RegionDesc* region = RegionDesc::GetRegionDescAt(addr);
122 region->SetRegionType(RegionDesc::RegionType::OLD_REGION);
123 Heap::GetHeap().SetGCReason(GC_REASON_YOUNG);
124 collector.SetGCReason(GC_REASON_YOUNG);
125
126 roots.push_back(obj);
127 collector.MarkingRoots(roots);
128 ASSERT_TRUE(region->IsInOldSpace());
129 }
130
HWTEST_F_L0(MarkingCollectorTest,PushRootToWorkStackTest)131 HWTEST_F_L0(MarkingCollectorTest, PushRootToWorkStackTest)
132 {
133 TableMarkingCollctor& collector = reinterpret_cast<TableMarkingCollctor&>(Heap::GetHeap().GetCollector());
134 RegionSpace& theAllocator = reinterpret_cast<RegionSpace&>(Heap::GetHeap().GetAllocator());
135 uintptr_t addr = theAllocator.AllocOldRegion();
136 ASSERT_NE(addr, 0);
137 BaseObject* obj = reinterpret_cast<BaseObject*>(addr);
138 RootSet roots;
139 RegionDesc* region = RegionDesc::GetRegionDescAt(addr);
140 region->SetRegionType(RegionDesc::RegionType::RECENT_LARGE_REGION);
141 collector.SetGCReason(GC_REASON_NATIVE);
142 region->MarkObject(obj);
143 bool result = collector.PushRootToWorkStack(&roots, obj);
144 ASSERT_FALSE(result);
145
146 region->SetRegionType(RegionDesc::RegionType::RECENT_LARGE_REGION);
147 collector.SetGCReason(GC_REASON_YOUNG);
148 result = collector.PushRootToWorkStack(&roots, obj);
149 ASSERT_FALSE(result);
150
151 region->SetRegionType(RegionDesc::RegionType::OLD_REGION);
152 collector.SetGCReason(GC_REASON_NATIVE);
153 result = collector.PushRootToWorkStack(&roots, obj);
154 ASSERT_FALSE(result);
155 }
156 }