• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021-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 #ifndef PANDA_RUNTIME_MEM_GC_GC_ADAPTIVE_STACK_H
16 #define PANDA_RUNTIME_MEM_GC_GC_ADAPTIVE_STACK_H
17 
18 #include "runtime/mem/gc/gc_root_type.h"
19 #include "runtime/mem/gc/workers/gc_workers_tasks.h"
20 #include "runtime/include/mem/panda_containers.h"
21 #include "runtime/mem/gc/g1/object_ref.h"
22 
23 namespace ark::mem {
24 
25 class GC;
26 
27 /*
28  * Adaptive stack with GC workers support.
29  * It will try to pop objects from the source stack and push
30  * it to the destination stack. if the destination stack reaches the limit,
31  * we will create a new task for worker.
32  * If stack limit is equal to zero, it means that the destination stack is unlimited.
33  */
34 template <typename Ref>
35 class GCAdaptiveStack {
36 public:
37     explicit GCAdaptiveStack(GC *gc, size_t stackSizeLimit = 0, size_t newTaskStackSizeLimit = 0,
38                              GCWorkersTaskTypes task = GCWorkersTaskTypes::TASK_EMPTY,
39                              uint64_t timeLimitForNewTaskCreation = 0, PandaDeque<Ref> *stackSrc = nullptr);
40 
41     virtual ~GCAdaptiveStack();
42     NO_COPY_SEMANTIC(GCAdaptiveStack);
43     NO_MOVE_SEMANTIC(GCAdaptiveStack);
44 
45     /**
46      * @brief Add new object into destination stack.
47      * If we set the limit for stack, we will create a new task for
48      * GC workers with it.
49      */
50     void PushToStack(Ref element);
51 
52     /**
53      * @brief Pop an object from source stack.
54      * If the source stack is empty, we will swap it with destination stack
55      * and return an object from it.
56      */
57     Ref PopFromStack();
58 
59     /**
60      * @brief Travers objects in stack via visitor and return marked objects.
61      * Visitor can push in stack, but mustn't pop from it.
62      */
63     template <typename Handler>
64     void TraverseObjects(Handler &handler);
65 
66     /// @brief Check that destination or source stack has at least one object.
67     bool Empty() const;
68     /// @brief Returns the sum of destination and source stacks sizes.
69     size_t Size() const;
70 
71     /**
72      * @brief Set the src stack pointer to nullptr.
73      * Should be used if we decide to free it not on destructor of this instance.
74      */
75     PandaDeque<Ref> *MoveStacksPointers();
76 
77     /// @brief Returns true if stack supports parallel workers, false otherwise
78     bool IsWorkersTaskSupported() const;
79 
80     /// @brief Remove all elements from stack
81     void Clear();
82 
SetTaskType(GCWorkersTaskTypes taskType)83     void SetTaskType(GCWorkersTaskTypes taskType)
84     {
85         taskType_ = taskType;
86     }
87 
GetTaskType()88     GCWorkersTaskTypes GetTaskType() const
89     {
90         return taskType_;
91     }
92 
93 protected:
94     virtual GCAdaptiveStack<Ref> *CreateStack() = 0;
95     virtual GCWorkersTask CreateTask(GCAdaptiveStack<Ref> *stack) = 0;
96 
GetStackSrc()97     PandaDeque<Ref> *&GetStackSrc()
98     {
99         return stackSrc_;
100     }
101 
GetStackDst()102     PandaDeque<Ref> *&GetStackDst()
103     {
104         return stackDst_;
105     }
106 
GetGC()107     GC *GetGC()
108     {
109         return gc_;
110     }
111 
GetNewTaskStackSizeLimit()112     size_t GetNewTaskStackSizeLimit() const
113     {
114         return newTaskStackSizeLimit_;
115     }
116 
GetTimeLimitForNewTaskCreation()117     uint64_t GetTimeLimitForNewTaskCreation() const
118     {
119         return timeLimitForNewTaskCreation_;
120     }
121 
122 private:
123     static constexpr size_t DEFAULT_TASKS_FOR_TIME_CHECK = 10;
124 
125     /**
126      * @brief Check tasks creation rate.
127      * If we create tasks too frequently, return true.
128      */
129     bool IsHighTaskCreationRate();
130 
131 private:
132     PandaDeque<Ref> *stackSrc_;
133     PandaDeque<Ref> *stackDst_;
134     size_t stackSizeLimit_ {0};
135     size_t initialStackSizeLimit_ {0};
136     size_t newTaskStackSizeLimit_ {0};
137     uint64_t startTime_ {0};
138     uint64_t timeLimitForNewTaskCreation_ {0};
139     size_t tasksForTimeCheck_ {DEFAULT_TASKS_FOR_TIME_CHECK};
140     size_t createdTasks_ {0};
141     GCWorkersTaskTypes taskType_;
142     GC *gc_;
143 };
144 }  // namespace ark::mem
145 
146 #endif  // PANDA_RUNTIME_MEM_GC_GC_ADAPTIVE_STACK_H
147