• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "runtime/include/mem/allocator-inl.h"
17 #include "runtime/mem/gc/g1/g1-allocator.h"
18 #include "runtime/mem/freelist_allocator-inl.h"
19 #include "runtime/mem/humongous_obj_allocator-inl.h"
20 #include "runtime/mem/pygote_space_allocator-inl.h"
21 
22 namespace panda::mem {
23 
24 template <MTModeT MTMode>
ObjectAllocatorG1(MemStatsType * mem_stats,bool create_pygote_space_allocator)25 ObjectAllocatorG1<MTMode>::ObjectAllocatorG1(MemStatsType *mem_stats, bool create_pygote_space_allocator)
26     : ObjectAllocatorGenBase(mem_stats, GCCollectMode::GC_ALL, create_pygote_space_allocator)
27 {
28     object_allocator_ = MakePandaUnique<ObjectAllocator>(mem_stats);
29     nonmovable_allocator_ = MakePandaUnique<NonMovableAllocator>(mem_stats, SpaceType::SPACE_TYPE_NON_MOVABLE_OBJECT);
30     humongous_object_allocator_ = MakePandaUnique<HumongousObjectAllocator>(mem_stats);
31     mem_stats_ = mem_stats;
32 }
33 
34 template <MTModeT MTMode>
GetRegularObjectMaxSize()35 size_t ObjectAllocatorG1<MTMode>::GetRegularObjectMaxSize()
36 {
37     return ObjectAllocator::GetMaxRegularObjectSize();
38 }
39 
40 template <MTModeT MTMode>
GetLargeObjectMaxSize()41 size_t ObjectAllocatorG1<MTMode>::GetLargeObjectMaxSize()
42 {
43     return ObjectAllocator::GetMaxRegularObjectSize();
44 }
45 
46 template <MTModeT MTMode>
IsAddressInYoungSpace(uintptr_t address)47 bool ObjectAllocatorG1<MTMode>::IsAddressInYoungSpace(uintptr_t address)
48 {
49     (void)address;
50     return false;
51 }
52 
53 template <MTModeT MTMode>
HasYoungSpace()54 bool ObjectAllocatorG1<MTMode>::HasYoungSpace()
55 {
56     return true;
57 }
58 
59 template <MTModeT MTMode>
GetYoungSpaceMemRange()60 MemRange ObjectAllocatorG1<MTMode>::GetYoungSpaceMemRange()
61 {
62     return MemRange(0, 1);
63 }
64 
65 template <MTModeT MTMode>
CreateNewTLAB(panda::ManagedThread * thread)66 TLAB *ObjectAllocatorG1<MTMode>::CreateNewTLAB([[maybe_unused]] panda::ManagedThread *thread)
67 {
68     return object_allocator_->CreateNewTLAB(thread, TLAB_SIZE);
69 }
70 
71 template <MTModeT MTMode>
GetTLABMaxAllocSize()72 size_t ObjectAllocatorG1<MTMode>::GetTLABMaxAllocSize()
73 {
74     return PANDA_TLAB_MAX_ALLOC_SIZE;
75 }
76 
77 template <MTModeT MTMode>
IterateOverObjectsInRange(MemRange mem_range,const ObjectVisitor & object_visitor)78 void ObjectAllocatorG1<MTMode>::IterateOverObjectsInRange(MemRange mem_range, const ObjectVisitor &object_visitor)
79 {
80     if (pygote_space_allocator_ != nullptr) {
81         pygote_space_allocator_->IterateOverObjectsInRange(object_visitor, ToVoidPtr(mem_range.GetStartAddress()),
82                                                            ToVoidPtr(mem_range.GetEndAddress()));
83     }
84     humongous_object_allocator_->IterateOverObjectsInRange(object_visitor, ToVoidPtr(mem_range.GetStartAddress()),
85                                                            ToVoidPtr(mem_range.GetEndAddress()));
86 }
87 
88 // ObjectAllocatorGen and ObjectAllocatorNoGen should have inheritance relationship
89 template <MTModeT MTMode>
ContainObject(const ObjectHeader * obj) const90 bool ObjectAllocatorG1<MTMode>::ContainObject(const ObjectHeader *obj) const
91 {
92     if (pygote_space_allocator_ != nullptr && pygote_space_allocator_->ContainObject(obj)) {
93         return true;
94     }
95     if (object_allocator_->ContainObject(obj)) {
96         return true;
97     }
98     if (humongous_object_allocator_->ContainObject(obj)) {
99         return true;
100     }
101 
102     return false;
103 }
104 
105 template <MTModeT MTMode>
IsLive(const ObjectHeader * obj)106 bool ObjectAllocatorG1<MTMode>::IsLive(const ObjectHeader *obj)
107 {
108     if (pygote_space_allocator_ != nullptr && pygote_space_allocator_->ContainObject(obj)) {
109         return pygote_space_allocator_->IsLive(obj);
110     }
111     if (object_allocator_->ContainObject(obj)) {
112         return object_allocator_->IsLive(obj);
113     }
114     if (humongous_object_allocator_->ContainObject(obj)) {
115         return humongous_object_allocator_->IsLive(obj);
116     }
117 
118     return false;
119 }
120 
121 template <MTModeT MTMode>
Allocate(size_t size,Alignment align,panda::ManagedThread * thread)122 void *ObjectAllocatorG1<MTMode>::Allocate(size_t size, Alignment align, [[maybe_unused]] panda::ManagedThread *thread)
123 {
124     void *mem = nullptr;
125     size_t aligned_size = AlignUp(size, GetAlignmentInBytes(align));
126     if (LIKELY(aligned_size <= REGION_SIZE)) {
127         mem = object_allocator_->Alloc(size, align);
128     } else {
129         mem = AllocateTenured(size);
130     }
131     return mem;
132 }
133 
134 template <MTModeT MTMode>
AllocateNonMovable(size_t size,Alignment align,panda::ManagedThread * thread)135 void *ObjectAllocatorG1<MTMode>::AllocateNonMovable(size_t size, Alignment align,
136                                                     [[maybe_unused]] panda::ManagedThread *thread)
137 {
138     // before pygote fork, allocate small non-movable objects in pygote space
139     if (UNLIKELY(IsPygoteAllocEnabled() && pygote_space_allocator_->CanAllocNonMovable(size, align))) {
140         return pygote_space_allocator_->Alloc(size, align);
141     }
142     void *mem = nullptr;
143     size_t aligned_size = AlignUp(size, GetAlignmentInBytes(align));
144     if (aligned_size <= ObjectAllocator::GetMaxRegularObjectSize()) {
145         mem = nonmovable_allocator_->Alloc(aligned_size, align);
146     } else {
147         // We don't need special allocator for this
148         // Humongous objects are non-movable
149         size_t pool_size = std::max(PANDA_DEFAULT_POOL_SIZE, HumongousObjectAllocator::GetMinPoolSize(size));
150         mem = AllocateSafe(size, align, humongous_object_allocator_.get(), pool_size,
151                            SpaceType::SPACE_TYPE_HUMONGOUS_OBJECT);
152     }
153     return mem;
154 }
155 
156 template <MTModeT MTMode>
AllocateTenured(size_t size)157 void *ObjectAllocatorG1<MTMode>::AllocateTenured(size_t size)
158 {
159     void *mem = nullptr;
160     Alignment align = DEFAULT_ALIGNMENT;
161     size_t aligned_size = AlignUp(size, GetAlignmentInBytes(align));
162     if (aligned_size <= ObjectAllocator::GetMaxRegularObjectSize()) {
163         mem = object_allocator_->Alloc<RegionFlag::IS_OLD>(size, align);
164     } else {
165         size_t pool_size = std::max(PANDA_DEFAULT_POOL_SIZE, HumongousObjectAllocator::GetMinPoolSize(size));
166         mem = AllocateSafe(size, align, humongous_object_allocator_.get(), pool_size,
167                            SpaceType::SPACE_TYPE_HUMONGOUS_OBJECT);
168     }
169     return mem;
170 }
171 
172 template <MTModeT MTMode>
VisitAndRemoveAllPools(const MemVisitor & mem_visitor)173 void ObjectAllocatorG1<MTMode>::VisitAndRemoveAllPools(const MemVisitor &mem_visitor)
174 {
175     if (pygote_space_allocator_ != nullptr) {
176         pygote_space_allocator_->VisitAndRemoveAllPools(mem_visitor);
177     }
178     object_allocator_->VisitAndRemoveAllPools(mem_visitor);
179     humongous_object_allocator_->VisitAndRemoveAllPools(mem_visitor);
180 }
181 
182 template <MTModeT MTMode>
VisitAndRemoveFreePools(const MemVisitor & mem_visitor)183 void ObjectAllocatorG1<MTMode>::VisitAndRemoveFreePools(const MemVisitor &mem_visitor)
184 {
185     if (pygote_space_allocator_ != nullptr) {
186         pygote_space_allocator_->VisitAndRemoveFreePools(mem_visitor);
187     }
188     humongous_object_allocator_->VisitAndRemoveFreePools(mem_visitor);
189 }
190 
191 template <MTModeT MTMode>
IterateOverYoungObjects(const ObjectVisitor & object_visitor)192 void ObjectAllocatorG1<MTMode>::IterateOverYoungObjects(const ObjectVisitor &object_visitor)
193 {
194     // Use CompactAllSpecificRegions method to compact young regions.
195     (void)object_visitor;
196     UNREACHABLE();
197 }
198 
199 template <MTModeT MTMode>
IterateOverTenuredObjects(const ObjectVisitor & object_visitor)200 void ObjectAllocatorG1<MTMode>::IterateOverTenuredObjects(const ObjectVisitor &object_visitor)
201 {
202     if (pygote_space_allocator_ != nullptr) {
203         pygote_space_allocator_->IterateOverObjects(object_visitor);
204     }
205     object_allocator_->IterateOverObjects(object_visitor);
206     humongous_object_allocator_->IterateOverObjects(object_visitor);
207 }
208 
209 template <MTModeT MTMode>
IterateOverObjects(const ObjectVisitor & object_visitor)210 void ObjectAllocatorG1<MTMode>::IterateOverObjects(const ObjectVisitor &object_visitor)
211 {
212     if (pygote_space_allocator_ != nullptr) {
213         pygote_space_allocator_->IterateOverObjects(object_visitor);
214     }
215     object_allocator_->IterateOverObjects(object_visitor);
216     humongous_object_allocator_->IterateOverObjects(object_visitor);
217 }
218 
219 template <MTModeT MTMode>
IterateRegularSizeObjects(const ObjectVisitor & object_visitor)220 void ObjectAllocatorG1<MTMode>::IterateRegularSizeObjects(const ObjectVisitor &object_visitor)
221 {
222     object_allocator_->IterateOverObjects(object_visitor);
223 }
224 
225 template <MTModeT MTMode>
IterateNonRegularSizeObjects(const ObjectVisitor & object_visitor)226 void ObjectAllocatorG1<MTMode>::IterateNonRegularSizeObjects(const ObjectVisitor &object_visitor)
227 {
228     if (pygote_space_allocator_ != nullptr) {
229         pygote_space_allocator_->IterateOverObjects(object_visitor);
230     }
231     humongous_object_allocator_->IterateOverObjects(object_visitor);
232 }
233 
234 template <MTModeT MTMode>
FreeObjectsMovedToPygoteSpace()235 void ObjectAllocatorG1<MTMode>::FreeObjectsMovedToPygoteSpace()
236 {
237     // Clear allocator because we have moved all objects in it to pygote space
238     object_allocator_.reset(new (std::nothrow) ObjectAllocator(mem_stats_));
239 }
240 
241 template <MTModeT MTMode>
Collect(const GCObjectVisitor & gc_object_visitor,GCCollectMode collect_mode)242 void ObjectAllocatorG1<MTMode>::Collect(const GCObjectVisitor &gc_object_visitor, GCCollectMode collect_mode)
243 {
244     switch (collect_mode) {
245         case GCCollectMode::GC_MINOR:
246             break;
247         case GCCollectMode::GC_ALL:
248         case GCCollectMode::GC_MAJOR:
249             if (pygote_space_allocator_ != nullptr) {
250                 pygote_space_allocator_->Collect(gc_object_visitor);
251             }
252             humongous_object_allocator_->Collect(gc_object_visitor);
253             break;
254         case GCCollectMode::GC_FULL:
255             UNREACHABLE();
256             break;
257         case GC_NONE:
258             UNREACHABLE();
259             break;
260         default:
261             UNREACHABLE();
262     }
263 }
264 
265 template <MTModeT MTMode>
ResetYoungAllocator()266 void ObjectAllocatorG1<MTMode>::ResetYoungAllocator()
267 {
268     object_allocator_->ResetAllSpecificRegions<RegionFlag::IS_EDEN>();
269 }
270 
271 template <MTModeT MTMode>
IsObjectInNonMovableSpace(const ObjectHeader * obj)272 bool ObjectAllocatorG1<MTMode>::IsObjectInNonMovableSpace(const ObjectHeader *obj)
273 {
274     return nonmovable_allocator_->ContainObject(obj);
275 }
276 
277 template class ObjectAllocatorG1<MT_MODE_SINGLE>;
278 template class ObjectAllocatorG1<MT_MODE_MULTI>;
279 
280 }  // namespace panda::mem
281