• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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