1 /** 2 * Copyright (c) 2021-2022 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/include/mem/panda_containers.h" 20 21 namespace panda::mem { 22 23 class GC; 24 25 enum class GCWorkersTaskTypes { 26 TASK_EMPTY, 27 TASK_MARKING, 28 TASK_REMARK, 29 TASK_REGION_COMPACTING, 30 TASK_ROOT_COLLECTION, 31 TASK_MOVE_YOUNG_ALIVE_OBJECTS, 32 TASK_INIT_REFS_FROM_REMSETS, 33 }; 34 35 /* 36 * Adaptive stack with GC workers support. 37 * It will try to pop objects from the source stack and push 38 * it to the destination stack. if the destination stack reaches the limit, 39 * we will create a new task for worker. 40 * If stack limit is equal to zero, it means that the destination stack is unlimited. 41 */ 42 class GCAdaptiveStack { 43 public: 44 explicit GCAdaptiveStack(GC *gc, size_t stack_size_limit = 0, size_t new_task_stack_size_limit = 0, 45 GCWorkersTaskTypes task = GCWorkersTaskTypes::TASK_EMPTY, 46 PandaStack<const ObjectHeader *> *stack_src = nullptr); 47 48 ~GCAdaptiveStack(); 49 NO_COPY_SEMANTIC(GCAdaptiveStack); 50 DEFAULT_MOVE_SEMANTIC(GCAdaptiveStack); 51 52 /** 53 * This method should be used when we find new object by field from another object. 54 * @param from_object from which object we found object by reference, nullptr for roots 55 * @param object object which will be added to the stack 56 */ 57 void PushToStack(const ObjectHeader *from_object, const ObjectHeader *object); 58 59 /** 60 * This method should be used when we find new object as a root 61 * @param root_type type of the root which we found 62 * @param object object which will be added to the stack 63 */ 64 void PushToStack(RootType root_type, const ObjectHeader *object); 65 66 /** 67 * \brief Pop an object from source stack. 68 * If the source stack is empty, we will swap it with destination stack 69 * and return an object from it. 70 */ 71 const ObjectHeader *PopFromStack(); 72 /** 73 * \brief Check that destination or source stack has at least one object. 74 */ 75 bool Empty(); 76 /** 77 * \brief Returns the sum of destination and source stacks sizes. 78 */ 79 size_t Size(); 80 81 /** 82 * \brief Set the src stack pointer to nullptr. 83 * Should be used if we decide to free it not on destructor of this instance. 84 */ 85 PandaStack<const ObjectHeader *> *MoveStacksPointers(); 86 87 /** 88 * \brief Returns true if stack supports parallel workers, false otherwise 89 */ 90 bool IsWorkersTaskSupported(); 91 92 /** 93 * \brief Remove all elements from stack 94 */ 95 void Clear(); 96 97 private: 98 /** 99 * \brief Add new object into destination stack. 100 * If we set the limit for stack, we will create a new task for 101 * GC workers with it. 102 */ 103 void PushToStack(const ObjectHeader *element); 104 105 private: 106 PandaStack<const ObjectHeader *> *stack_src_; 107 PandaStack<const ObjectHeader *> *stack_dst_; 108 size_t stack_size_limit_ {0}; 109 size_t initial_stack_size_limit_ {0}; 110 size_t new_task_stack_size_limit_ {0}; 111 GCWorkersTaskTypes task_type_; 112 GC *gc_; 113 }; 114 115 } // namespace panda::mem 116 117 #endif // PANDA_RUNTIME_MEM_GC_GC_H 118