• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
16 #ifndef LIBPANDABASE_MEM_POOL_MAP_H
17 #define LIBPANDABASE_MEM_POOL_MAP_H
18 
19 #include <array>
20 #include <cstddef>
21 #include <cstdint>
22 
23 #include "macros.h"
24 #include "mem.h"
25 #include "space.h"
26 
27 WEAK_FOR_LTO_START
28 
29 namespace panda {
30 
31 enum class AllocatorType {
32     UNDEFINED,
33     RUNSLOTS_ALLOCATOR,
34     FREELIST_ALLOCATOR,
35     HUMONGOUS_ALLOCATOR,
36     ARENA_ALLOCATOR,
37     TLAB_ALLOCATOR,
38     BUMP_ALLOCATOR,
39     REGION_ALLOCATOR,
40     FRAME_ALLOCATOR,
41     BUMP_ALLOCATOR_WITH_TLABS,
42 };
43 
44 class AllocatorInfo {
45 public:
AllocatorInfo(AllocatorType type,const void * addr)46     explicit constexpr AllocatorInfo(AllocatorType type, const void *addr) : type_(type), header_addr_(addr)
47     {
48         // We can't create AllocatorInfo without correct pointer to the allocator header
49         ASSERT(header_addr_ != nullptr);
50     }
51 
GetType()52     AllocatorType GetType() const
53     {
54         return type_;
55     }
56 
GetAllocatorHeaderAddr()57     const void *GetAllocatorHeaderAddr() const
58     {
59         return header_addr_;
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 *header_addr_;
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     void AddPoolToMap(const void *pool_addr, size_t pool_size, SpaceType space_type, AllocatorType allocator_type,
77                       const void *allocator_addr);
78     void RemovePoolFromMap(const void *pool_addr, size_t pool_size);
79     // Get Allocator info for the object allocated at this address.
80     AllocatorInfo GetAllocatorInfo(const void *addr) const;
81 
82     void *GetFirstByteOfPoolForAddr(const void *addr) const;
83 
84     SpaceType GetSpaceType(const void *addr) const;
85 
86     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 = PANDA_POOL_ALIGNMENT_IN_BYTES;
91     static constexpr size_t POOL_MAP_SIZE = POOL_MAP_COVERAGE / POOL_MAP_GRANULARITY;
92 
93     static constexpr bool FIRST_BYTE_IN_SEGMENT_VALUE = true;
94 
95     class PoolInfo {
96     public:
Initialize(bool first_byte_in_segment,SpaceType space_type,AllocatorType allocator_type,const void * allocator_addr)97         void Initialize(bool first_byte_in_segment, SpaceType space_type, AllocatorType allocator_type,
98                         const void *allocator_addr)
99         {
100             ASSERT(first_byte_in_segment_ == FIRST_BYTE_IN_SEGMENT_VALUE);
101             ASSERT(allocator_type_ == AllocatorType::UNDEFINED);
102             // Added a TSAN ignore here because TSAN thinks
103             // that we can have a data race here - concurrent
104             // initialization and reading.
105             // However, we can't get an access for this fields
106             // without initialization in the correct flow.
107             TSAN_ANNOTATE_IGNORE_WRITES_BEGIN();
108             first_byte_in_segment_ = first_byte_in_segment;
109             allocator_addr_ = allocator_addr;
110             space_type_ = space_type;
111             allocator_type_ = allocator_type;
112             TSAN_ANNOTATE_IGNORE_WRITES_END();
113         }
114 
IsEmpty()115         inline bool IsEmpty() const
116         {
117             return space_type_ == SpaceType::SPACE_TYPE_UNDEFINED;
118         }
119 
Destroy()120         void Destroy()
121         {
122             first_byte_in_segment_ = FIRST_BYTE_IN_SEGMENT_VALUE;
123             allocator_addr_ = nullptr;
124             allocator_type_ = AllocatorType::UNDEFINED;
125             space_type_ = SpaceType::SPACE_TYPE_UNDEFINED;
126         }
127 
IsFirstByteInSegment()128         bool IsFirstByteInSegment() const
129         {
130             return first_byte_in_segment_ == FIRST_BYTE_IN_SEGMENT_VALUE;
131         }
132 
GetAllocatorType()133         AllocatorType GetAllocatorType() const
134         {
135             return allocator_type_;
136         }
137 
GetAllocatorAddr()138         const void *GetAllocatorAddr() const
139         {
140             return allocator_addr_;
141         }
142 
GetSpaceType()143         SpaceType GetSpaceType() const
144         {
145             return space_type_;
146         }
147 
148     private:
149         bool first_byte_in_segment_ {FIRST_BYTE_IN_SEGMENT_VALUE};
150         AllocatorType allocator_type_ {AllocatorType::UNDEFINED};
151         SpaceType space_type_ {SpaceType::SPACE_TYPE_UNDEFINED};
152         const void *allocator_addr_ = nullptr;
153     };
154 
AddrToMapNum(const void * addr)155     static size_t AddrToMapNum(const void *addr)
156     {
157         size_t map_num = ToUintPtr(addr) / POOL_MAP_GRANULARITY;
158         ASSERT(map_num < POOL_MAP_SIZE);
159         return map_num;
160     }
161 
MapNumToAddr(size_t map_num)162     static void *MapNumToAddr(size_t map_num)
163     {
164         // Checking overflow
165         ASSERT(static_cast<uint64_t>(map_num) * POOL_MAP_GRANULARITY == map_num * POOL_MAP_GRANULARITY);
166         return ToVoidPtr(map_num * POOL_MAP_GRANULARITY);
167     }
168 
169     void *GetFirstByteInSegment(const void *addr) const;
170 
171     std::array<PoolInfo, POOL_MAP_SIZE> pool_map_;
172 
173     friend class PoolMapTest;
174 };
175 
176 }  // namespace panda
177 
178 WEAK_FOR_LTO_END
179 
180 #endif  // LIBPANDABASE_MEM_POOL_MAP_H
181