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