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_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 panda::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 *mem_stats); 65 66 NO_COPY_SEMANTIC(InternalAllocator); 67 NO_MOVE_SEMANTIC(InternalAllocator); 68 69 template <AllocScope AllocScopeT = 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 mem_visitor); 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 mem_visitor); 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 *local_allocator, 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 *local_allocator); 145 146 static void InitInternalAllocatorFromRuntime(Allocator *allocator); 147 148 static Allocator *GetInternalAllocatorFromRuntime(); 149 150 static void ClearInternalAllocatorFromRuntime(); 151 152 private: 153 #ifdef TRACK_INTERNAL_ALLOCATIONS 154 os::memory::Mutex lock_; 155 MemStatsType *mem_stats_; 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 AllocScopeT> 163 void *AllocViaPandaAllocators(size_t size, Alignment align); 164 void FreeViaPandaAllocators(void *ptr); 165 RunSlotsAllocatorT *runslots_allocator_ {nullptr}; 166 FreeListAllocatorT *freelist_allocator_ {nullptr}; 167 HumongousObjAllocatorT *humongous_allocator_ {nullptr}; 168 MallocProxyAllocatorT *malloc_allocator_ {nullptr}; 169 static Allocator *allocator_from_runtime; 170 171 friend class test::InternalAllocatorTest; 172 }; 173 174 } // namespace panda::mem 175 176 #endif // PANDA_RUNTIME_MEM_INTERNAL_ALLOCATOR_H 177