1 /**
2 * Copyright (c) 2023-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 #ifndef PANDA_RUNTIME_MEM_GC_GC_WORKERS_TASKS_H
17 #define PANDA_RUNTIME_MEM_GC_GC_WORKERS_TASKS_H
18
19 #include "runtime/mem/gc/g1/ref_updater.h"
20 #include "runtime/mem/gc/gc_root.h"
21 #include "runtime/thread_pool_queue.h"
22 #include "libpandabase/utils/range.h"
23
24 namespace ark::mem {
25
26 enum class GCWorkersTaskTypes : uint32_t {
27 TASK_EMPTY,
28 TASK_MARKING,
29 TASK_REMARK,
30 TASK_HUGE_ARRAY_MARKING_REMARK,
31 TASK_XREMARK,
32 TASK_FULL_MARK,
33 TASK_REGION_COMPACTING,
34 TASK_RETURN_FREE_PAGES_TO_OS,
35 TASK_UPDATE_REMSET_REFS,
36 TASK_ENQUEUE_REMSET_REFS,
37 TASK_EVACUATE_REGIONS,
38 TASK_MARK_WHOLE_REGION,
39 };
40
GCWorkersTaskTypesToString(GCWorkersTaskTypes type)41 constexpr const char *GCWorkersTaskTypesToString(GCWorkersTaskTypes type)
42 {
43 switch (type) {
44 case GCWorkersTaskTypes::TASK_EMPTY:
45 return "Empty task";
46 case GCWorkersTaskTypes::TASK_MARKING:
47 return "Marking task";
48 case GCWorkersTaskTypes::TASK_REMARK:
49 return "Remark task";
50 case GCWorkersTaskTypes::TASK_HUGE_ARRAY_MARKING_REMARK:
51 return "Huge array marking task during remark";
52 case GCWorkersTaskTypes::TASK_XREMARK:
53 return "XRemark task";
54 case GCWorkersTaskTypes::TASK_FULL_MARK:
55 return "Marking task for full collection";
56 case GCWorkersTaskTypes::TASK_REGION_COMPACTING:
57 return "Region compacting task";
58 case GCWorkersTaskTypes::TASK_RETURN_FREE_PAGES_TO_OS:
59 return "Return free pages to the OS";
60 case GCWorkersTaskTypes::TASK_UPDATE_REMSET_REFS:
61 return "Update remset references task";
62 case GCWorkersTaskTypes::TASK_ENQUEUE_REMSET_REFS:
63 return "Enqueue remset references task";
64 case GCWorkersTaskTypes::TASK_EVACUATE_REGIONS:
65 return "Evacuate regions task";
66 case GCWorkersTaskTypes::TASK_MARK_WHOLE_REGION:
67 return "Mark whole region task";
68 default:
69 return "Unknown task";
70 }
71 }
72
73 class GCWorkersTask : public TaskInterface {
74 public:
taskType_(type)75 explicit GCWorkersTask(GCWorkersTaskTypes type = GCWorkersTaskTypes::TASK_EMPTY) : taskType_(type)
76 {
77 ASSERT(type == GCWorkersTaskTypes::TASK_EMPTY || type == GCWorkersTaskTypes::TASK_RETURN_FREE_PAGES_TO_OS ||
78 type == GCWorkersTaskTypes::TASK_MARK_WHOLE_REGION);
79 }
80
81 ~GCWorkersTask() = default;
82 DEFAULT_COPY_SEMANTIC(GCWorkersTask);
83 DEFAULT_MOVE_SEMANTIC(GCWorkersTask);
84
IsEmpty()85 bool IsEmpty() const
86 {
87 return taskType_ == GCWorkersTaskTypes::TASK_EMPTY;
88 }
89
90 template <class GCWorkersTaskT>
Cast()91 std::enable_if_t<std::is_base_of_v<GCWorkersTask, GCWorkersTaskT>, GCWorkersTaskT *> Cast() const
92 {
93 return static_cast<GCWorkersTaskT *>(const_cast<GCWorkersTask *>(this));
94 }
95
96 template <class GCWorkersTaskT>
97 std::enable_if_t<!std::is_base_of_v<GCWorkersTask, GCWorkersTaskT>, GCWorkersTaskT *> Cast() const = delete;
98
GetType()99 GCWorkersTaskTypes GetType() const
100 {
101 return taskType_;
102 }
103
104 private:
105 GCWorkersTaskTypes taskType_;
106
107 protected:
108 using StorageType = void *;
109
GCWorkersTask(GCWorkersTaskTypes type,StorageType taskStorageData)110 GCWorkersTask(GCWorkersTaskTypes type, StorageType taskStorageData) : taskType_(type), storage_(taskStorageData)
111 {
112 ASSERT(storage_ != nullptr);
113 }
114
115 StorageType storage_ {nullptr}; // NOLINT(misc-non-private-member-variables-in-classes)
116 };
117
118 class GCMarkWorkersTask : public GCWorkersTask {
119 public:
120 using StackType = GCMarkingStackType;
GCMarkWorkersTask(GCWorkersTaskTypes type,StackType * markingStack)121 GCMarkWorkersTask(GCWorkersTaskTypes type, StackType *markingStack) : GCWorkersTask(type, markingStack)
122 {
123 ASSERT(type == GCWorkersTaskTypes::TASK_MARKING || type == GCWorkersTaskTypes::TASK_REMARK ||
124 type == GCWorkersTaskTypes::TASK_HUGE_ARRAY_MARKING_REMARK || type == GCWorkersTaskTypes::TASK_XREMARK ||
125 type == GCWorkersTaskTypes::TASK_FULL_MARK);
126 }
127 DEFAULT_COPY_SEMANTIC(GCMarkWorkersTask);
128 DEFAULT_MOVE_SEMANTIC(GCMarkWorkersTask);
129 ~GCMarkWorkersTask() = default;
130
GetMarkingStack()131 StackType *GetMarkingStack() const
132 {
133 return static_cast<StackType *>(storage_);
134 }
135 };
136
137 class Region;
138
139 class GCRegionCompactWorkersTask : public GCWorkersTask {
140 public:
141 using RegionDataType = std::pair<Region *, ObjectVisitor>;
142
GCRegionCompactWorkersTask(RegionDataType * regionData)143 explicit GCRegionCompactWorkersTask(RegionDataType *regionData)
144 : GCWorkersTask(GCWorkersTaskTypes::TASK_REGION_COMPACTING, regionData)
145 {
146 }
147 DEFAULT_COPY_SEMANTIC(GCRegionCompactWorkersTask);
148 DEFAULT_MOVE_SEMANTIC(GCRegionCompactWorkersTask);
149 ~GCRegionCompactWorkersTask() = default;
150
GetRegionData()151 RegionDataType *GetRegionData() const
152 {
153 return static_cast<RegionDataType *>(storage_);
154 }
155 };
156
157 template <bool VECTOR>
158 class GCUpdateRefsWorkersTask : public GCWorkersTask {
159 public:
160 using MovedObjectsRange = std::conditional_t<VECTOR, Range<PandaVector<ObjectHeader *>::iterator>,
161 Range<PandaDeque<ObjectHeader *>::iterator>>;
162 // We need this to evenly split moved objects vector to ranges for gc workers
163 static constexpr int RANGE_SIZE = 4096;
164
GCUpdateRefsWorkersTask(MovedObjectsRange * movedObjects)165 explicit GCUpdateRefsWorkersTask(MovedObjectsRange *movedObjects)
166 : GCWorkersTask(GCWorkersTaskTypes::TASK_ENQUEUE_REMSET_REFS, movedObjects)
167 {
168 }
169 DEFAULT_COPY_SEMANTIC(GCUpdateRefsWorkersTask);
170 DEFAULT_MOVE_SEMANTIC(GCUpdateRefsWorkersTask);
171 ~GCUpdateRefsWorkersTask() = default;
172
GetMovedObjectsRange()173 MovedObjectsRange *GetMovedObjectsRange() const
174 {
175 return static_cast<MovedObjectsRange *>(storage_);
176 }
177 };
178
179 class GCMarkWholeRegionTask : public GCWorkersTask {
180 public:
GCMarkWholeRegionTask(Region * region,PandaDeque<ObjectHeader * > * markedObjDeque)181 explicit GCMarkWholeRegionTask(Region *region, PandaDeque<ObjectHeader *> *markedObjDeque)
182 : GCWorkersTask(GCWorkersTaskTypes::TASK_MARK_WHOLE_REGION), region_(region), markedObjDeque_(markedObjDeque)
183 {
184 }
185 DEFAULT_COPY_SEMANTIC(GCMarkWholeRegionTask);
186 DEFAULT_MOVE_SEMANTIC(GCMarkWholeRegionTask);
187 ~GCMarkWholeRegionTask() = default;
188
GetInfo()189 std::pair<Region *, PandaDeque<ObjectHeader *> *> GetInfo() const
190 {
191 return std::make_pair(region_, markedObjDeque_);
192 }
193
194 private:
195 Region *region_;
196 PandaDeque<ObjectHeader *> *markedObjDeque_;
197 };
198
199 } // namespace ark::mem
200
201 #endif // PANDA_RUNTIME_MEM_GC_GC_WORKERS_TASKS_H
202