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 RUNTIME_MEM_PANDA_BUMP_ALLOCATOR_H 16 #define RUNTIME_MEM_PANDA_BUMP_ALLOCATOR_H 17 18 #include <functional> 19 #include <memory> 20 21 #include "mem/mem_pool.h" 22 #include "libpandabase/macros.h" 23 #include "libpandabase/mem/arena-inl.h" 24 #include "libpandabase/mem/mem.h" 25 #include "libpandabase/mem/mem_range.h" 26 #include "runtime/mem/tlab.h" 27 #include "runtime/mem/lock_config_helper.h" 28 29 namespace ark { 30 class ObjectHeader; 31 } // namespace ark 32 33 namespace ark::mem { 34 35 class BumpPointerAllocatorLockConfig { 36 public: 37 using CommonLock = os::memory::Mutex; 38 using DummyLock = os::memory::DummyLock; 39 40 template <MTModeT MT_MODE> 41 using ParameterizedLock = typename LockConfigHelper<BumpPointerAllocatorLockConfig, MT_MODE>::Value; 42 }; 43 44 // This allocator can allocate memory as a BumpPointerAllocator 45 // and also can allocate big pieces of memory for the TLABs. 46 // 47 // Structure: 48 // 49 // |------------------------------------------------------------------------------------------------------------| 50 // | Memory Pool | 51 // |------------------------------------------------------------------------------------------------------------| 52 // | allocated objects | unused memory | memory for TLABs | 53 // |---------------------------|------------------------------|-------------------------------------------------| 54 // |xxxxxxxxxx|xxxxxx|xxxxxxxxx| | || || | 55 // |xxxxxxxxxx|xxxxxx|xxxxxxxxx| | || || | 56 // |xxxxxxxxxx|xxxxxx|xxxxxxxxx| free memory | TLAB 3 || TLAB 2 || TLAB 1 | 57 // |xxxxxxxxxx|xxxxxx|xxxxxxxxx| | || || | 58 // |xxxxxxxxxx|xxxxxx|xxxxxxxxx| | || || | 59 // |------------------------------------------------------------------------------------------------------------| 60 // 61 62 template <typename AllocConfigT, typename LockConfigT = BumpPointerAllocatorLockConfig::CommonLock, 63 bool USE_TLABS = false> 64 class BumpPointerAllocator { 65 public: 66 DEFAULT_NOEXCEPT_MOVE_SEMANTIC(BumpPointerAllocator); 67 NO_COPY_SEMANTIC(BumpPointerAllocator); 68 ~BumpPointerAllocator(); 69 70 BumpPointerAllocator() = delete; 71 72 TLAB *CreateNewTLAB(size_t size); 73 74 /** 75 * Construct BumpPointer allocator with provided pool 76 * @param pool - pool 77 */ 78 explicit BumpPointerAllocator(Pool pool, SpaceType typeAllocation, MemStatsType *memStats, 79 size_t tlabsMaxCount = 0); 80 81 [[nodiscard]] void *Alloc(size_t size, Alignment alignment = ark::DEFAULT_ALIGNMENT); 82 83 void VisitAndRemoveAllPools(const MemVisitor &memVisitor); 84 85 void VisitAndRemoveFreePools(const MemVisitor &memVisitor); 86 87 /** 88 * @brief Iterates over all objects allocated by this allocator 89 * @param object_visitor 90 */ 91 void IterateOverObjects(const std::function<void(ObjectHeader *objectHeader)> &objectVisitor); 92 93 /** 94 * @brief Iterates over objects in the range inclusively. 95 * @tparam MemVisitor 96 * @param mem_visitor - function pointer or functor 97 * @param left_border - a pointer to the first byte of the range 98 * @param right_border - a pointer to the last byte of the range 99 */ 100 template <typename MemVisitor> 101 void IterateOverObjectsInRange(const MemVisitor &memVisitor, void *leftBorder, void *rightBorder); 102 103 /// Resets to the "all clear" state 104 void Reset(); 105 106 /** 107 * @brief Add an extra memory pool to the allocator. 108 * The memory pool must be located just after the current memory given to this allocator. 109 * @param mem - pointer to the extra memory pool. 110 * @param size - a size of the extra memory pool. 111 */ 112 void ExpandMemory(void *mem, size_t size); 113 114 /** 115 * Get MemRange used by allocator 116 * @return MemRange for allocator 117 */ 118 MemRange GetMemRange(); 119 120 // BumpPointer allocator can't be used for simple collection. 121 // Only for CollectAndMove. 122 void Collect(GCObjectVisitor deathCheckerFn) = delete; 123 124 /** 125 * Collects dead objects and move alive with provided visitor 126 * @param death_checker - functor for check if object alive 127 * @param object_move_visitor - object visitor 128 */ 129 template <typename ObjectMoveVisitorT> 130 void CollectAndMove(const GCObjectVisitor &deathChecker, const ObjectMoveVisitorT &objectMoveVisitor); 131 GetAllocatorType()132 static constexpr AllocatorType GetAllocatorType() 133 { 134 return AllocatorType::BUMP_ALLOCATOR; 135 } 136 137 bool ContainObject(const ObjectHeader *obj); 138 139 bool IsLive(const ObjectHeader *obj); 140 141 private: 142 class TLABsManager { 143 public: TLABsManager(size_t tlabsMaxCount)144 explicit TLABsManager(size_t tlabsMaxCount) : tlabsMaxCount_(tlabsMaxCount), tlabs_(tlabsMaxCount) {} 145 Reset()146 void Reset() 147 { 148 for (size_t i = 0; i < curTlabNum_; i++) { 149 tlabs_[i].Fill(nullptr, 0); 150 } 151 curTlabNum_ = 0; 152 tlabsOccupiedSize_ = 0; 153 } 154 GetUnusedTLABInstance()155 TLAB *GetUnusedTLABInstance() 156 { 157 if (curTlabNum_ < tlabsMaxCount_) { 158 return &tlabs_[curTlabNum_++]; 159 } 160 return nullptr; 161 } 162 163 template <class Visitor> IterateOverTLABs(const Visitor & visitor)164 void IterateOverTLABs(const Visitor &visitor) 165 { 166 for (size_t i = 0; i < curTlabNum_; i++) { 167 if (!visitor(&tlabs_[i])) { 168 return; 169 } 170 } 171 } 172 GetTLABsOccupiedSize()173 size_t GetTLABsOccupiedSize() 174 { 175 return tlabsOccupiedSize_; 176 } 177 IncreaseTLABsOccupiedSize(size_t size)178 void IncreaseTLABsOccupiedSize(size_t size) 179 { 180 tlabsOccupiedSize_ += size; 181 } 182 183 private: 184 size_t curTlabNum_ {0}; 185 size_t tlabsMaxCount_; 186 std::vector<TLAB> tlabs_; 187 size_t tlabsOccupiedSize_ {0}; 188 }; 189 190 // Mutex, which allows only one thread to Alloc/Free/Collect/Iterate inside this allocator 191 LockConfigT allocatorLock_; 192 Arena arena_; 193 TLABsManager tlabManager_; 194 SpaceType typeAllocation_; 195 MemStatsType *memStats_; 196 }; 197 198 } // namespace ark::mem 199 200 #endif // RUNTIME_MEM_PANDA_BUMP_ALLOCATOR_H 201