• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/allocator/fix_heap.h"
17 
18 #include "common_components/heap/ark_collector/ark_collector.h"
19 #include "common_runtime/hooks.h"
20 
21 namespace common {
22 
CollectFixHeapTasks(FixHeapTaskList & taskList,RegionList & list,FixRegionType type)23 void FixHeapWorker::CollectFixHeapTasks(FixHeapTaskList &taskList, RegionList &list, FixRegionType type)
24 {
25     list.VisitAllRegions([&taskList, type](RegionDesc *region) { taskList.emplace_back(region, type); });
26 }
27 
FixOldRegion(RegionDesc * region)28 void FixHeapWorker::FixOldRegion(RegionDesc *region)
29 {
30     auto visitFunc = [this, &region](BaseObject *object) {
31         DLOG(FIX, "fix: old obj %p<%p>(%zu)", object, object->GetTypeInfo(), object->GetSize());
32         collector_->FixObjectRefFields(object);
33     };
34     region->VisitRememberSet(visitFunc);
35 }
36 
FixRecentOldRegion(RegionDesc * region)37 void FixHeapWorker::FixRecentOldRegion(RegionDesc *region)
38 {
39     auto visitFunc = [this, &region](BaseObject *object) {
40         DLOG(FIX, "fix: old obj %p<%p>(%zu)", object, object->GetTypeInfo(), object->GetSize());
41         collector_->FixObjectRefFields(object);
42     };
43     region->VisitRememberSetBeforeCopy(visitFunc);
44 }
45 
FixToRegion(RegionDesc * region)46 void FixHeapWorker::FixToRegion(RegionDesc *region)
47 {
48     region->VisitAllObjects([this](BaseObject *object) { collector_->FixObjectRefFields(object); });
49 }
50 
51 template <FixHeapWorker::DeadObjectHandlerType type>
FixRegion(RegionDesc * region)52 void FixHeapWorker::FixRegion(RegionDesc *region)
53 {
54     size_t cellCount = 0;
55     if constexpr (type == FixHeapWorker::COLLECT_FIXED_PINNED) {
56         cellCount = region->GetRegionCellCount();
57     }
58 
59     region->VisitAllObjects([this, region, cellCount](BaseObject *object) {
60         if (collector_->IsSurvivedObject(object)) {
61             collector_->FixObjectRefFields(object);
62         } else {
63             if constexpr (type == FixHeapWorker::FILL_FREE) {
64                 FillFreeObject(object, RegionSpace::GetAllocSize(*object));
65             } else if constexpr (type == FixHeapWorker::COLLECT_FIXED_PINNED) {
66                 result_.fixedPinnedGarbages.emplace_back(region, object, cellCount);
67             } else if constexpr (type == FixHeapWorker::COLLECT_PINNED) {
68                 result_.pinnedGarbages.emplace_back(object, RegionSpace::GetAllocSize(*object));
69             } else if constexpr (type == FixHeapWorker::IGNORED) {
70                 /* Ignore */
71             }
72             DLOG(FIX, "fix: skip dead obj %p<%p>(%zu)", object, object->GetTypeInfo(), object->GetSize());
73         }
74     });
75 }
76 
77 template <FixHeapWorker::DeadObjectHandlerType type>
FixRecentRegion(RegionDesc * region)78 void FixHeapWorker::FixRecentRegion(RegionDesc *region)
79 {
80     size_t cellCount = 0;
81     if constexpr (type == FixHeapWorker::COLLECT_FIXED_PINNED) {
82         cellCount = region->GetRegionCellCount();
83     }
84 
85     region->VisitAllObjectsBeforeCopy([this, region, cellCount](BaseObject *object) {
86         if (region->IsNewObjectSinceMarking(object) || collector_->IsSurvivedObject(object)) {
87             collector_->FixObjectRefFields(object);
88         } else {  // handle dead objects in tl-regions for concurrent gc.
89             if constexpr (type == FixHeapWorker::FILL_FREE) {
90                 FillFreeObject(object, RegionSpace::GetAllocSize(*object));
91             } else if constexpr (type == FixHeapWorker::COLLECT_FIXED_PINNED) {
92                 result_.fixedPinnedGarbages.emplace_back(region, object, cellCount);
93             } else if constexpr (type == FixHeapWorker::COLLECT_PINNED) {
94                 result_.pinnedGarbages.emplace_back(object, RegionSpace::GetAllocSize(*object));
95             } else if constexpr (type == FixHeapWorker::IGNORED) {
96                 /* Ignore */
97             }
98             DLOG(FIX, "skip dead obj %p<%p>(%zu)", object, object->GetTypeInfo(), object->GetSize());
99         }
100     });
101 }
102 
Run(uint32_t threadIndex)103 bool FixHeapWorker::Run([[maybe_unused]] uint32_t threadIndex)
104 {
105     ThreadLocal::SetThreadType(ThreadType::GC_THREAD);
106     auto *task = getNextTask_();
107     while (task != nullptr) {
108         DispatchRegionFixTask(task);
109         task = getNextTask_();
110     }
111     ThreadLocal::SetThreadType(ThreadType::ARK_PROCESSOR);
112     monitor_.NotifyFinishOne();
113     return true;
114 }
115 
DispatchRegionFixTask(FixHeapTask * task)116 void FixHeapWorker::DispatchRegionFixTask(FixHeapTask *task)
117 {
118     result_.numProcessedRegions += 1;
119     RegionDesc *region = task->region;
120     switch (task->type) {
121         case FIX_OLD_REGION:
122             FixOldRegion(region);
123             break;
124         case FIX_RECENT_OLD_REGION:
125             FixRecentOldRegion(region);
126             break;
127         case FIX_RECENT_REGION:
128             if (region->IsFixedRegion()) {
129                 FixRecentRegion<COLLECT_FIXED_PINNED>(region);
130             } else if (region->IsPinnedRegion()) {
131                 FixRecentRegion<COLLECT_PINNED>(region);
132             } else if (region->IsLargeRegion()) {
133                 FixRecentRegion<IGNORED>(region);
134             } else {
135                 FixRecentRegion<FILL_FREE>(region);
136             }
137             break;
138         case FIX_REGION:
139             if (region->IsFixedRegion()) {
140                 FixRegion<COLLECT_FIXED_PINNED>(region);
141             } else if (region->IsPinnedRegion()) {
142                 FixRegion<COLLECT_PINNED>(region);
143             } else if (region->IsLargeRegion()) {
144                 FixRegion<IGNORED>(region);
145             } else {
146                 FixRegion<FILL_FREE>(region);
147             }
148             break;
149         case FIX_TO_REGION:
150             FixToRegion(region);
151             break;
152         default:
153             UNREACHABLE();
154     }
155 }
156 
157 std::stack<std::pair<RegionList *, RegionDesc *>> PostFixHeapWorker::emptyRegionsToCollect {};
158 
PostClearTask()159 void PostFixHeapWorker::PostClearTask()
160 {
161     for (auto [region, object, cellCount] : result_.fixedPinnedGarbages) {
162         region->CollectPinnedGarbage(object, cellCount);
163     }
164     for (auto [object, size] : result_.pinnedGarbages) {
165         FillFreeObject(object, size);
166     }
167     DLOG(FIX, "Fix heap worker processed %d Regions, %d fixedPinnedGarbages, %d pinnedGarbages",
168          result_.numProcessedRegions, result_.fixedPinnedGarbages.size(), result_.pinnedGarbages.size());
169 }
170 
Run(uint32_t threadIndex)171 bool PostFixHeapWorker::Run([[maybe_unused]] uint32_t threadIndex)
172 {
173     ThreadLocal::SetThreadType(ThreadType::GC_THREAD);
174     PostClearTask();
175     ThreadLocal::SetThreadType(ThreadType::ARK_PROCESSOR);
176     monitor_.NotifyFinishOne();
177     return true;
178 }
179 
AddEmptyRegionToCollectDuringPostFix(RegionList * list,RegionDesc * region)180 void PostFixHeapWorker::AddEmptyRegionToCollectDuringPostFix(RegionList *list, RegionDesc *region)
181 {
182     PostFixHeapWorker::emptyRegionsToCollect.emplace(list, region);
183 }
184 
CollectEmptyRegions()185 void PostFixHeapWorker::CollectEmptyRegions()
186 {
187     RegionSpace &theAllocator = reinterpret_cast<RegionSpace &>(Heap::GetHeap().GetAllocator());
188     RegionManager &regionManager = theAllocator.GetRegionManager();
189     GCStats &stats = Heap::GetHeap().GetCollector().GetGCStats();
190     size_t garbageSize = 0;
191 
192     while (!PostFixHeapWorker::emptyRegionsToCollect.empty()) {
193         auto [list, del] = PostFixHeapWorker::emptyRegionsToCollect.top();
194         PostFixHeapWorker::emptyRegionsToCollect.pop();
195 
196         list->DeleteRegion(del);
197         garbageSize += regionManager.CollectRegion(del);
198     }
199     stats.pinnedGarbageSize += garbageSize;
200 }
201 
202 };  // namespace common
203