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