• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 RUNTIME_MEM_PANDA_BUMP_ALLOCATOR_H
16 #define RUNTIME_MEM_PANDA_BUMP_ALLOCATOR_H
17 
18 #include <functional>
19 #include <memory>
20 
21 #include "mem/mem_pool.h"
22 #include "libpandabase/macros.h"
23 #include "libpandabase/mem/arena-inl.h"
24 #include "libpandabase/mem/mem.h"
25 #include "libpandabase/mem/mem_range.h"
26 #include "runtime/mem/tlab.h"
27 #include "runtime/mem/lock_config_helper.h"
28 
29 namespace ark {
30 class ObjectHeader;
31 }  // namespace ark
32 
33 namespace ark::mem {
34 
35 class BumpPointerAllocatorLockConfig {
36 public:
37     using CommonLock = os::memory::Mutex;
38     using DummyLock = os::memory::DummyLock;
39 
40     template <MTModeT MT_MODE>
41     using ParameterizedLock = typename LockConfigHelper<BumpPointerAllocatorLockConfig, MT_MODE>::Value;
42 };
43 
44 // This allocator can allocate memory as a BumpPointerAllocator
45 // and also can allocate big pieces of memory for the TLABs.
46 //
47 // Structure:
48 //
49 //  |------------------------------------------------------------------------------------------------------------|
50 //  |                                                 Memory Pool                                                |
51 //  |------------------------------------------------------------------------------------------------------------|
52 //  |     allocated objects     |         unused memory        |                 memory for TLABs                |
53 //  |---------------------------|------------------------------|-------------------------------------------------|
54 //  |xxxxxxxxxx|xxxxxx|xxxxxxxxx|                              |               ||               ||               |
55 //  |xxxxxxxxxx|xxxxxx|xxxxxxxxx|                              |               ||               ||               |
56 //  |xxxxxxxxxx|xxxxxx|xxxxxxxxx|           free memory        |     TLAB 3    ||     TLAB 2    ||     TLAB 1    |
57 //  |xxxxxxxxxx|xxxxxx|xxxxxxxxx|                              |               ||               ||               |
58 //  |xxxxxxxxxx|xxxxxx|xxxxxxxxx|                              |               ||               ||               |
59 //  |------------------------------------------------------------------------------------------------------------|
60 //
61 
62 template <typename AllocConfigT, typename LockConfigT = BumpPointerAllocatorLockConfig::CommonLock,
63           bool USE_TLABS = false>
64 class BumpPointerAllocator {
65 public:
66     DEFAULT_NOEXCEPT_MOVE_SEMANTIC(BumpPointerAllocator);
67     NO_COPY_SEMANTIC(BumpPointerAllocator);
68     ~BumpPointerAllocator();
69 
70     BumpPointerAllocator() = delete;
71 
72     TLAB *CreateNewTLAB(size_t size);
73 
74     /**
75      * Construct BumpPointer allocator with provided pool
76      * @param pool - pool
77      */
78     explicit BumpPointerAllocator(Pool pool, SpaceType typeAllocation, MemStatsType *memStats,
79                                   size_t tlabsMaxCount = 0);
80 
81     [[nodiscard]] void *Alloc(size_t size, Alignment alignment = ark::DEFAULT_ALIGNMENT);
82 
83     void VisitAndRemoveAllPools(const MemVisitor &memVisitor);
84 
85     void VisitAndRemoveFreePools(const MemVisitor &memVisitor);
86 
87     /**
88      * @brief Iterates over all objects allocated by this allocator
89      * @param object_visitor
90      */
91     void IterateOverObjects(const std::function<void(ObjectHeader *objectHeader)> &objectVisitor);
92 
93     /**
94      * @brief Iterates over objects in the range inclusively.
95      * @tparam MemVisitor
96      * @param mem_visitor - function pointer or functor
97      * @param left_border - a pointer to the first byte of the range
98      * @param right_border - a pointer to the last byte of the range
99      */
100     template <typename MemVisitor>
101     void IterateOverObjectsInRange(const MemVisitor &memVisitor, void *leftBorder, void *rightBorder);
102 
103     /// Resets to the "all clear" state
104     void Reset();
105 
106     /**
107      * @brief Add an extra memory pool to the allocator.
108      * The memory pool must be located just after the current memory given to this allocator.
109      * @param mem - pointer to the extra memory pool.
110      * @param size - a size of the extra memory pool.
111      */
112     void ExpandMemory(void *mem, size_t size);
113 
114     /**
115      * Get MemRange used by allocator
116      * @return MemRange for allocator
117      */
118     MemRange GetMemRange();
119 
120     // BumpPointer allocator can't be used for simple collection.
121     // Only for CollectAndMove.
122     void Collect(GCObjectVisitor deathCheckerFn) = delete;
123 
124     /**
125      * Collects dead objects and move alive with provided visitor
126      * @param death_checker - functor for check if object alive
127      * @param object_move_visitor - object visitor
128      */
129     template <typename ObjectMoveVisitorT>
130     void CollectAndMove(const GCObjectVisitor &deathChecker, const ObjectMoveVisitorT &objectMoveVisitor);
131 
GetAllocatorType()132     static constexpr AllocatorType GetAllocatorType()
133     {
134         return AllocatorType::BUMP_ALLOCATOR;
135     }
136 
137     bool ContainObject(const ObjectHeader *obj);
138 
139     bool IsLive(const ObjectHeader *obj);
140 
141 private:
142     class TLABsManager {
143     public:
TLABsManager(size_t tlabsMaxCount)144         explicit TLABsManager(size_t tlabsMaxCount) : tlabsMaxCount_(tlabsMaxCount), tlabs_(tlabsMaxCount) {}
145 
Reset()146         void Reset()
147         {
148             for (size_t i = 0; i < curTlabNum_; i++) {
149                 tlabs_[i].Fill(nullptr, 0);
150             }
151             curTlabNum_ = 0;
152             tlabsOccupiedSize_ = 0;
153         }
154 
GetUnusedTLABInstance()155         TLAB *GetUnusedTLABInstance()
156         {
157             if (curTlabNum_ < tlabsMaxCount_) {
158                 return &tlabs_[curTlabNum_++];
159             }
160             return nullptr;
161         }
162 
163         template <class Visitor>
IterateOverTLABs(const Visitor & visitor)164         void IterateOverTLABs(const Visitor &visitor)
165         {
166             for (size_t i = 0; i < curTlabNum_; i++) {
167                 if (!visitor(&tlabs_[i])) {
168                     return;
169                 }
170             }
171         }
172 
GetTLABsOccupiedSize()173         size_t GetTLABsOccupiedSize()
174         {
175             return tlabsOccupiedSize_;
176         }
177 
IncreaseTLABsOccupiedSize(size_t size)178         void IncreaseTLABsOccupiedSize(size_t size)
179         {
180             tlabsOccupiedSize_ += size;
181         }
182 
183     private:
184         size_t curTlabNum_ {0};
185         size_t tlabsMaxCount_;
186         std::vector<TLAB> tlabs_;
187         size_t tlabsOccupiedSize_ {0};
188     };
189 
190     // Mutex, which allows only one thread to Alloc/Free/Collect/Iterate inside this allocator
191     LockConfigT allocatorLock_;
192     Arena arena_;
193     TLABsManager tlabManager_;
194     SpaceType typeAllocation_;
195     MemStatsType *memStats_;
196 };
197 
198 }  // namespace ark::mem
199 
200 #endif  // RUNTIME_MEM_PANDA_BUMP_ALLOCATOR_H
201