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