1 /**
2 * Copyright (c) 2023-2024 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_FULL_MARK,
31 TASK_REGION_COMPACTING,
32 TASK_RETURN_FREE_PAGES_TO_OS,
33 TASK_UPDATE_REMSET_REFS,
34 TASK_ENQUEUE_REMSET_REFS,
35 TASK_EVACUATE_REGIONS,
36 };
37
GCWorkersTaskTypesToString(GCWorkersTaskTypes type)38 constexpr const char *GCWorkersTaskTypesToString(GCWorkersTaskTypes type)
39 {
40 switch (type) {
41 case GCWorkersTaskTypes::TASK_EMPTY:
42 return "Empty task";
43 case GCWorkersTaskTypes::TASK_MARKING:
44 return "Marking task";
45 case GCWorkersTaskTypes::TASK_REMARK:
46 return "Remark task";
47 case GCWorkersTaskTypes::TASK_FULL_MARK:
48 return "Marking task for full collection";
49 case GCWorkersTaskTypes::TASK_REGION_COMPACTING:
50 return "Region compacting task";
51 case GCWorkersTaskTypes::TASK_RETURN_FREE_PAGES_TO_OS:
52 return "Return free pages to the OS";
53 case GCWorkersTaskTypes::TASK_UPDATE_REMSET_REFS:
54 return "Update remset references task";
55 case GCWorkersTaskTypes::TASK_ENQUEUE_REMSET_REFS:
56 return "Enqueue remset references task";
57 case GCWorkersTaskTypes::TASK_EVACUATE_REGIONS:
58 return "Evacuate regions task";
59 default:
60 return "Unknown task";
61 }
62 }
63
64 class GCWorkersTask : public TaskInterface {
65 public:
taskType_(type)66 explicit GCWorkersTask(GCWorkersTaskTypes type = GCWorkersTaskTypes::TASK_EMPTY) : taskType_(type)
67 {
68 ASSERT(type == GCWorkersTaskTypes::TASK_EMPTY || type == GCWorkersTaskTypes::TASK_RETURN_FREE_PAGES_TO_OS);
69 }
70
71 ~GCWorkersTask() = default;
72 DEFAULT_COPY_SEMANTIC(GCWorkersTask);
73 DEFAULT_MOVE_SEMANTIC(GCWorkersTask);
74
IsEmpty()75 bool IsEmpty() const
76 {
77 return taskType_ == GCWorkersTaskTypes::TASK_EMPTY;
78 }
79
80 template <class GCWorkersTaskT>
Cast()81 std::enable_if_t<std::is_base_of_v<GCWorkersTask, GCWorkersTaskT>, GCWorkersTaskT *> Cast() const
82 {
83 return static_cast<GCWorkersTaskT *>(const_cast<GCWorkersTask *>(this));
84 }
85
86 template <class GCWorkersTaskT>
87 std::enable_if_t<!std::is_base_of_v<GCWorkersTask, GCWorkersTaskT>, GCWorkersTaskT *> Cast() const = delete;
88
GetType()89 GCWorkersTaskTypes GetType() const
90 {
91 return taskType_;
92 }
93
94 private:
95 GCWorkersTaskTypes taskType_;
96
97 protected:
98 using StorageType = void *;
99
GCWorkersTask(GCWorkersTaskTypes type,StorageType taskStorageData)100 GCWorkersTask(GCWorkersTaskTypes type, StorageType taskStorageData) : taskType_(type), storage_(taskStorageData)
101 {
102 ASSERT(storage_ != nullptr);
103 }
104
105 StorageType storage_ {nullptr}; // NOLINT(misc-non-private-member-variables-in-classes)
106 };
107
108 class GCMarkWorkersTask : public GCWorkersTask {
109 public:
110 using StackType = GCMarkingStackType;
GCMarkWorkersTask(GCWorkersTaskTypes type,StackType * markingStack)111 GCMarkWorkersTask(GCWorkersTaskTypes type, StackType *markingStack) : GCWorkersTask(type, markingStack)
112 {
113 ASSERT(type == GCWorkersTaskTypes::TASK_MARKING || type == GCWorkersTaskTypes::TASK_REMARK ||
114 type == GCWorkersTaskTypes::TASK_FULL_MARK);
115 }
116 DEFAULT_COPY_SEMANTIC(GCMarkWorkersTask);
117 DEFAULT_MOVE_SEMANTIC(GCMarkWorkersTask);
118 ~GCMarkWorkersTask() = default;
119
GetMarkingStack()120 StackType *GetMarkingStack() const
121 {
122 return static_cast<StackType *>(storage_);
123 }
124 };
125
126 class Region;
127
128 class GCRegionCompactWorkersTask : public GCWorkersTask {
129 public:
130 using RegionDataType = std::pair<Region *, ObjectVisitor>;
131
GCRegionCompactWorkersTask(RegionDataType * regionData)132 explicit GCRegionCompactWorkersTask(RegionDataType *regionData)
133 : GCWorkersTask(GCWorkersTaskTypes::TASK_REGION_COMPACTING, regionData)
134 {
135 }
136 DEFAULT_COPY_SEMANTIC(GCRegionCompactWorkersTask);
137 DEFAULT_MOVE_SEMANTIC(GCRegionCompactWorkersTask);
138 ~GCRegionCompactWorkersTask() = default;
139
GetRegionData()140 RegionDataType *GetRegionData() const
141 {
142 return static_cast<RegionDataType *>(storage_);
143 }
144 };
145
146 template <bool VECTOR>
147 class GCUpdateRefsWorkersTask : public GCWorkersTask {
148 public:
149 using MovedObjectsRange = std::conditional_t<VECTOR, Range<PandaVector<ObjectHeader *>::iterator>,
150 Range<PandaDeque<ObjectHeader *>::iterator>>;
151 // We need this to evenly split moved objects vector to ranges for gc workers
152 static constexpr int RANGE_SIZE = 4096;
153
GCUpdateRefsWorkersTask(MovedObjectsRange * movedObjects)154 explicit GCUpdateRefsWorkersTask(MovedObjectsRange *movedObjects)
155 : GCWorkersTask(GCWorkersTaskTypes::TASK_ENQUEUE_REMSET_REFS, movedObjects)
156 {
157 }
158 DEFAULT_COPY_SEMANTIC(GCUpdateRefsWorkersTask);
159 DEFAULT_MOVE_SEMANTIC(GCUpdateRefsWorkersTask);
160 ~GCUpdateRefsWorkersTask() = default;
161
GetMovedObjectsRange()162 MovedObjectsRange *GetMovedObjectsRange() const
163 {
164 return static_cast<MovedObjectsRange *>(storage_);
165 }
166 };
167
168 } // namespace ark::mem
169
170 #endif // PANDA_RUNTIME_MEM_GC_GC_WORKERS_TASKS_H
171