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 16 #ifndef LIBPANDABASE_MEM_POOL_MAP_H 17 #define LIBPANDABASE_MEM_POOL_MAP_H 18 19 #include <cstddef> 20 #include <array> 21 #include "macros.h" 22 #include "mem.h" 23 #include "space.h" 24 25 WEAK_FOR_LTO_START 26 27 namespace ark { 28 29 enum class AllocatorType : uint16_t { 30 UNDEFINED, 31 RUNSLOTS_ALLOCATOR, 32 FREELIST_ALLOCATOR, 33 HUMONGOUS_ALLOCATOR, 34 ARENA_ALLOCATOR, 35 TLAB_ALLOCATOR, 36 BUMP_ALLOCATOR, 37 REGION_ALLOCATOR, 38 FRAME_ALLOCATOR, 39 STACK_LIKE_ALLOCATOR, 40 BUMP_ALLOCATOR_WITH_TLABS, 41 NATIVE_STACKS_ALLOCATOR, 42 }; 43 44 class AllocatorInfo { 45 public: AllocatorInfo(AllocatorType type,const void * addr)46 explicit constexpr AllocatorInfo(AllocatorType type, const void *addr) : type_(type), headerAddr_(addr) 47 { 48 // We can't create AllocatorInfo without correct pointer to the allocator header 49 ASSERT(headerAddr_ != nullptr); 50 } 51 GetType()52 AllocatorType GetType() const 53 { 54 return type_; 55 } 56 GetAllocatorHeaderAddr()57 const void *GetAllocatorHeaderAddr() const 58 { 59 return headerAddr_; 60 } 61 62 virtual ~AllocatorInfo() = default; 63 64 DEFAULT_COPY_SEMANTIC(AllocatorInfo); 65 DEFAULT_MOVE_SEMANTIC(AllocatorInfo); 66 67 private: 68 AllocatorType type_; 69 const void *headerAddr_; 70 }; 71 72 // PoolMap is used to manage all pools which has been given to the allocators. 73 // It can be used to find which allocator has been used to allocate an object. 74 class PoolMap { 75 public: 76 PANDA_PUBLIC_API void AddPoolToMap(const void *poolAddr, size_t poolSize, SpaceType spaceType, 77 AllocatorType allocatorType, const void *allocatorAddr); 78 PANDA_PUBLIC_API void RemovePoolFromMap(const void *poolAddr, size_t poolSize); 79 // Get Allocator info for the object allocated at this address. 80 PANDA_PUBLIC_API AllocatorInfo GetAllocatorInfo(const void *addr) const; 81 82 PANDA_PUBLIC_API void *GetFirstByteOfPoolForAddr(const void *addr) const; 83 84 PANDA_PUBLIC_API SpaceType GetSpaceType(const void *addr) const; 85 86 PANDA_PUBLIC_API bool IsEmpty() const; 87 88 private: 89 static constexpr uint64_t POOL_MAP_COVERAGE = PANDA_MAX_HEAP_SIZE; 90 static constexpr size_t POOL_MAP_GRANULARITY_SHIFT = 18; 91 static constexpr size_t POOL_MAP_GRANULARITY_MASK = (1U << POOL_MAP_GRANULARITY_SHIFT) - 1U; 92 static_assert(PANDA_POOL_ALIGNMENT_IN_BYTES == 1U << POOL_MAP_GRANULARITY_SHIFT); 93 static constexpr size_t POOL_MAP_SIZE = POOL_MAP_COVERAGE >> POOL_MAP_GRANULARITY_SHIFT; 94 95 static constexpr bool FIRST_BYTE_IN_SEGMENT_VALUE = true; 96 97 using MapNumType = size_t; 98 99 class PoolInfo { 100 public: Initialize(MapNumType segmentFirstMapNum,SpaceType spaceType,AllocatorType allocatorType,const void * allocatorAddr)101 void Initialize(MapNumType segmentFirstMapNum, SpaceType spaceType, AllocatorType allocatorType, 102 const void *allocatorAddr) 103 { 104 ASSERT(allocatorType_ == AllocatorType::UNDEFINED); 105 // Added a TSAN ignore here because TSAN thinks 106 // that we can have a data race here - concurrent 107 // initialization and reading. 108 // However, we can't get an access for this fields 109 // without initialization in the correct flow. 110 TSAN_ANNOTATE_IGNORE_WRITES_BEGIN(); 111 segmentFirstMapNum_ = segmentFirstMapNum; 112 allocatorAddr_ = allocatorAddr; 113 spaceType_ = spaceType; 114 allocatorType_ = allocatorType; 115 TSAN_ANNOTATE_IGNORE_WRITES_END(); 116 } 117 IsEmpty()118 inline bool IsEmpty() const 119 { 120 return spaceType_ == SpaceType::SPACE_TYPE_UNDEFINED; 121 } 122 Destroy()123 void Destroy() 124 { 125 segmentFirstMapNum_ = 0; 126 allocatorAddr_ = nullptr; 127 allocatorType_ = AllocatorType::UNDEFINED; 128 spaceType_ = SpaceType::SPACE_TYPE_UNDEFINED; 129 } 130 GetSegmentFirstMapNum()131 MapNumType GetSegmentFirstMapNum() const 132 { 133 ASSERT(spaceType_ != SpaceType::SPACE_TYPE_UNDEFINED); 134 return segmentFirstMapNum_; 135 } 136 GetAllocatorType()137 AllocatorType GetAllocatorType() const 138 { 139 return allocatorType_; 140 } 141 GetAllocatorAddr()142 const void *GetAllocatorAddr() const 143 { 144 return allocatorAddr_; 145 } 146 GetSpaceType()147 SpaceType GetSpaceType() const 148 { 149 return spaceType_; 150 } 151 152 private: 153 AllocatorType allocatorType_ {AllocatorType::UNDEFINED}; 154 SpaceType spaceType_ {SpaceType::SPACE_TYPE_UNDEFINED}; 155 MapNumType segmentFirstMapNum_ {0}; 156 const void *allocatorAddr_ = nullptr; 157 }; 158 AddrToMapNum(const void * addr)159 static MapNumType AddrToMapNum(const void *addr) 160 { 161 MapNumType mapNum = ToUintPtr(addr) >> POOL_MAP_GRANULARITY_SHIFT; 162 ASSERT(mapNum < POOL_MAP_SIZE); 163 return mapNum; 164 } 165 MapNumToAddr(MapNumType mapNum)166 static void *MapNumToAddr(MapNumType mapNum) 167 { 168 // Checking overflow 169 ASSERT(static_cast<uint64_t>(mapNum) << POOL_MAP_GRANULARITY_SHIFT == mapNum << POOL_MAP_GRANULARITY_SHIFT); 170 return ToVoidPtr(mapNum << POOL_MAP_GRANULARITY_SHIFT); 171 } 172 173 std::array<PoolInfo, POOL_MAP_SIZE> poolMap_; 174 175 friend class PoolMapTest; 176 }; 177 178 } // namespace ark 179 180 WEAK_FOR_LTO_END 181 182 #endif // LIBPANDABASE_MEM_POOL_MAP_H 183