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