• 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 
22 namespace ark::mem {
23 
24 class GC;
25 
26 /*
27  * Adaptive stack with GC workers support.
28  * It will try to pop objects from the source stack and push
29  * it to the destination stack. if the destination stack reaches the limit,
30  * we will create a new task for worker.
31  * If stack limit is equal to zero, it means that the destination stack is unlimited.
32  */
33 class GCAdaptiveStack {
34 public:
35     using ObjectVisitor = std::function<void(const ObjectHeader *)>;
36     using MarkedObjects = PandaVector<PandaDeque<ObjectHeader *> *>;
37 
38     explicit GCAdaptiveStack(GC *gc, size_t stackSizeLimit = 0, size_t newTaskStackSizeLimit = 0,
39                              GCWorkersTaskTypes task = GCWorkersTaskTypes::TASK_EMPTY,
40                              uint64_t timeLimitForNewTaskCreation = 0, PandaDeque<ObjectHeader *> *stackSrc = nullptr);
41 
42     ~GCAdaptiveStack();
43     NO_COPY_SEMANTIC(GCAdaptiveStack);
44     DEFAULT_MOVE_SEMANTIC(GCAdaptiveStack);
45 
46     /**
47      * This method should be used when we find new object by field from another object.
48      * @param from_object from which object we found object by reference, nullptr for roots
49      * @param object object which will be added to the stack
50      */
51     void PushToStack(const ObjectHeader *fromObject, ObjectHeader *object);
52 
53     /**
54      * This method should be used when we find new object as a root
55      * @param root_type type of the root which we found
56      * @param object object which will be added to the stack
57      */
58     void PushToStack(RootType rootType, ObjectHeader *object);
59 
60     /**
61      * @brief Pop an object from source stack.
62      * If the source stack is empty, we will swap it with destination stack
63      * and return an object from it.
64      */
65     ObjectHeader *PopFromStack();
66 
67     /**
68      * @brief Travers objects in stack via visitor and return marked objects.
69      * Visitor can push in stack, but mustn't pop from it.
70      */
71     MarkedObjects TraverseObjects(const ObjectVisitor &visitor);
72 
73     /// @brief Check that destination or source stack has at least one object.
74     bool Empty();
75     /// @brief Returns the sum of destination and source stacks sizes.
76     size_t Size();
77 
78     /**
79      * @brief Set the src stack pointer to nullptr.
80      * Should be used if we decide to free it not on destructor of this instance.
81      */
82     PandaDeque<ObjectHeader *> *MoveStacksPointers();
83 
84     /// @brief Returns true if stack supports parallel workers, false otherwise
85     bool IsWorkersTaskSupported();
86 
87     /// @brief Remove all elements from stack
88     void Clear();
89 
90 private:
91     static constexpr size_t DEFAULT_TASKS_FOR_TIME_CHECK = 10;
92 
93     /**
94      * @brief Add new object into destination stack.
95      * If we set the limit for stack, we will create a new task for
96      * GC workers with it.
97      */
98     void PushToStack(ObjectHeader *element);
99 
100     /**
101      * @brief Check tasks creation rate.
102      * If we create tasks too frequently, return true.
103      */
104     bool IsHighTaskCreationRate();
105 
106 private:
107     PandaDeque<ObjectHeader *> *stackSrc_;
108     PandaDeque<ObjectHeader *> *stackDst_;
109     size_t stackSizeLimit_ {0};
110     size_t initialStackSizeLimit_ {0};
111     size_t newTaskStackSizeLimit_ {0};
112     uint64_t startTime_ {0};
113     uint64_t timeLimitForNewTaskCreation_ {0};
114     size_t tasksForTimeCheck_ {DEFAULT_TASKS_FOR_TIME_CHECK};
115     size_t createdTasks_ {0};
116     GCWorkersTaskTypes taskType_;
117     GC *gc_;
118 };
119 
120 }  // namespace ark::mem
121 
122 #endif  // PANDA_RUNTIME_MEM_GC_GC_H
123