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_INTERNAL_ALLOCATOR_H 16 #define PANDA_RUNTIME_MEM_INTERNAL_ALLOCATOR_H 17 18 #include <vector> 19 20 #include "libpandabase/concepts.h" 21 #include "libpandabase/mem/mmap_mem_pool-inl.h" 22 #include "libpandabase/mem/pool_manager.h" 23 #include "libpandabase/os/mutex.h" 24 #include "runtime/mem/freelist_allocator.h" 25 #include "runtime/mem/humongous_obj_allocator.h" 26 #include "runtime/mem/runslots_allocator.h" 27 28 #ifdef TRACK_INTERNAL_ALLOCATIONS 29 #include "libpandabase/mem/alloc_tracker.h" 30 #endif // TRACK_INTERNAL_ALLOCATIONS 31 32 namespace ark::mem { 33 34 namespace test { 35 class InternalAllocatorTest; 36 } // namespace test 37 38 template <typename AllocConfigT> 39 class MallocProxyAllocator; 40 class Allocator; 41 42 enum class AllocScope { 43 GLOBAL, // The allocation will be in global storage 44 LOCAL // The allocation will be in thread-local storage 45 }; 46 47 enum class InternalAllocatorConfig { 48 PANDA_ALLOCATORS, // Use panda allocators as internal allocator 49 MALLOC_ALLOCATOR // Use malloc allocator as internal allocator 50 }; 51 52 class RawMemoryConfig; 53 class EmptyMemoryConfig; 54 55 template <InternalAllocatorConfig CONFIG = InternalAllocatorConfig::PANDA_ALLOCATORS> 56 class InternalAllocator { 57 #ifdef NDEBUG 58 using InternalAllocConfigT = EmptyMemoryConfig; 59 #else 60 using InternalAllocConfigT = RawMemoryConfig; 61 #endif 62 63 public: 64 explicit InternalAllocator(MemStatsType *memStats); 65 66 NO_COPY_SEMANTIC(InternalAllocator); 67 NO_MOVE_SEMANTIC(InternalAllocator); 68 69 template <AllocScope ALLOC_SCOPE_T = AllocScope::GLOBAL> 70 [[nodiscard]] void *Alloc(size_t size, Alignment align = DEFAULT_ALIGNMENT); 71 72 [[nodiscard]] void *AllocLocal(size_t size, Alignment align = DEFAULT_ALIGNMENT) 73 { 74 return Alloc<AllocScope::LOCAL>(size, align); 75 } 76 77 template <class T> 78 [[nodiscard]] T *AllocArray(size_t size); 79 80 template <class T> 81 [[nodiscard]] T *AllocArrayLocal(size_t size); 82 83 template <typename T, typename... Args> 84 [[nodiscard]] std::enable_if_t<!std::is_array_v<T>, T *> New(Args &&...args); 85 86 template <typename T> 87 [[nodiscard]] std::enable_if_t<is_unbounded_array_v<T>, std::remove_extent_t<T> *> New(size_t size); 88 89 template <typename T> 90 void DeleteArray(T *data); 91 92 void Free(void *ptr); 93 94 #ifdef TRACK_INTERNAL_ALLOCATIONS Dump()95 void Dump() 96 { 97 tracker_->Dump(); 98 } 99 #endif // TRACK_INTERNAL_ALLOCATIONS 100 101 template <class T> 102 void Delete(T *ptr); 103 104 ~InternalAllocator(); 105 106 /** 107 * @brief Iterates over memory pools used by this allocator. 108 * @tparam MemVisitor 109 * @param mem_visitor - function pointer or functor 110 */ 111 template <typename MemVisitor> 112 void VisitAndRemoveAllPools(MemVisitor memVisitor); 113 114 /** 115 * @brief Visit memory pools that can be returned to the system in this allocator 116 * and remove them from the allocator structure. 117 * @tparam MemVisitor 118 * @param mem_visitor - function pointer or functor 119 */ 120 template <typename MemVisitor> 121 void VisitAndRemoveFreePools(MemVisitor memVisitor); 122 123 using LocalSmallObjectAllocator = RunSlotsAllocator<InternalAllocConfigT, RunSlotsAllocatorLockConfig::DummyLock>; 124 125 /** 126 * @brief Create and set up local internal allocator instance for fast small objects allocation 127 * @param allocator - a pointer to the allocator which will be used for local allocator instance storage 128 * @return - a pointer to the local internal allocator instance 129 */ 130 static InternalAllocator::LocalSmallObjectAllocator *SetUpLocalInternalAllocator(Allocator *allocator); 131 132 /** 133 * @brief Delete local internal allocator instance and return all pools to the system 134 * @param allocator - a pointer to the allocator which was used for local allocator instance storage 135 * @param local_allocator - a pointer to the local internal allocator instance 136 */ 137 static void FinalizeLocalInternalAllocator(LocalSmallObjectAllocator *localAllocator, Allocator *allocator); 138 139 /** 140 * @brief Return free memory pools to the system in local internal allocator 141 * and remove them from the allocator structure. 142 * @param local_allocator - a pointer to a local internal allocator instance 143 */ 144 static void RemoveFreePoolsForLocalInternalAllocator(LocalSmallObjectAllocator *localAllocator); 145 146 static void InitInternalAllocatorFromRuntime(Allocator *allocator); 147 148 static PANDA_PUBLIC_API Allocator *GetInternalAllocatorFromRuntime(); 149 150 static void ClearInternalAllocatorFromRuntime(); 151 152 private: 153 #ifdef TRACK_INTERNAL_ALLOCATIONS 154 os::memory::Mutex lock_; 155 MemStatsType *memStats_; 156 AllocTracker *tracker_ = nullptr; 157 #endif // TRACK_INTERNAL_ALLOCATIONS 158 using RunSlotsAllocatorT = RunSlotsAllocator<InternalAllocConfigT>; 159 using FreeListAllocatorT = FreeListAllocator<InternalAllocConfigT>; 160 using HumongousObjAllocatorT = HumongousObjAllocator<InternalAllocConfigT>; 161 using MallocProxyAllocatorT = MallocProxyAllocator<InternalAllocConfigT>; 162 template <AllocScope ALLOC_SCOPE_T> 163 void *AllocViaPandaAllocators(size_t size, Alignment align); 164 template <AllocScope ALLOC_SCOPE_T> 165 void *AllocViaRunSlotsAllocator(size_t size, Alignment align); 166 void *AllocViaFreeListAllocator(size_t size, Alignment align); 167 void *AllocViaHumongousAllocator(size_t size, Alignment align); 168 void FreeViaPandaAllocators(void *ptr); 169 RunSlotsAllocatorT *runslotsAllocator_ {nullptr}; 170 FreeListAllocatorT *freelistAllocator_ {nullptr}; 171 HumongousObjAllocatorT *humongousAllocator_ {nullptr}; 172 MallocProxyAllocatorT *mallocAllocator_ {nullptr}; 173 static Allocator *allocatorFromRuntime_; 174 175 friend class test::InternalAllocatorTest; 176 }; 177 178 } // namespace ark::mem 179 180 #endif // PANDA_RUNTIME_MEM_INTERNAL_ALLOCATOR_H 181