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 RUNTIME_MEM_GC_G1_G1_ALLOCATOR_H 17 #define RUNTIME_MEM_GC_G1_G1_ALLOCATOR_H 18 19 #include "runtime/include/mem/allocator.h" 20 #include "runtime/mem/region_allocator.h" 21 #include "runtime/mem/region_allocator-inl.h" 22 #include "runtime/mem/gc/g1/g1-allocator_constants.h" 23 24 namespace panda::mem { 25 class ObjectAllocConfigWithCrossingMap; 26 class ObjectAllocConfig; 27 class TLAB; 28 29 template <MTModeT MT_MODE = MT_MODE_MULTI> 30 class ObjectAllocatorG1 final : public ObjectAllocatorGenBase { 31 static constexpr size_t TLAB_SIZE = 4_KB; // TLAB size for young gen 32 33 using ObjectAllocator = RegionAllocator<ObjectAllocConfig>; 34 using NonMovableAllocator = RegionNonmovableAllocator<ObjectAllocConfig, RegionAllocatorLockConfig::CommonLock, 35 FreeListAllocator<ObjectAllocConfig>>; 36 using HumongousObjectAllocator = 37 RegionHumongousAllocator<ObjectAllocConfig>; // Allocator used for humongous objects 38 39 // REGION_SIZE should not change here. 40 // If it is necessary to change this value, it must be done through changes to G1_REGION_SIZE 41 static constexpr size_t REGION_SIZE = mem::G1_REGION_SIZE; 42 static_assert(REGION_SIZE == mem::G1_REGION_SIZE); 43 44 public: 45 NO_MOVE_SEMANTIC(ObjectAllocatorG1); 46 NO_COPY_SEMANTIC(ObjectAllocatorG1); 47 48 explicit ObjectAllocatorG1(MemStatsType *memStats, bool createPygoteSpaceAllocator); 49 50 ~ObjectAllocatorG1() final = default; 51 52 void *Allocate(size_t size, Alignment align, [[maybe_unused]] panda::ManagedThread *thread, 53 ObjMemInitPolicy objInit) final; 54 55 void *AllocateNonMovable(size_t size, Alignment align, [[maybe_unused]] panda::ManagedThread *thread, 56 ObjMemInitPolicy objInit) final; 57 58 void PinObject(ObjectHeader *object) final; 59 60 void UnpinObject(ObjectHeader *object) final; 61 62 void VisitAndRemoveAllPools(const MemVisitor &memVisitor) final; 63 64 void VisitAndRemoveFreePools(const MemVisitor &memVisitor) final; 65 66 void IterateOverYoungObjects(const ObjectVisitor &objectVisitor) final; 67 68 size_t GetMaxYoungRegionsCount(); 69 70 PandaVector<Region *> GetYoungRegions(); 71 72 PandaVector<Region *> GetMovableRegions(); 73 74 PandaVector<Region *> GetAllRegions(); 75 76 /// Returns a vector which contains non-movable and humongous regions 77 PandaVector<Region *> GetNonRegularRegions(); 78 79 void IterateOverTenuredObjects(const ObjectVisitor &objectVisitor) final; 80 81 void IterateOverHumongousObjects(const ObjectVisitor &objectVisitor); 82 83 void IterateOverObjects(const ObjectVisitor &objectVisitor) final; 84 85 /// @brief iterates all objects in object allocator 86 void IterateRegularSizeObjects(const ObjectVisitor &objectVisitor) final; 87 88 /// @brief iterates objects in all allocators except object allocator 89 void IterateNonRegularSizeObjects(const ObjectVisitor &objectVisitor) final; 90 91 void FreeObjectsMovedToPygoteSpace() final; 92 Collect(const GCObjectVisitor & gcObjectVisitor,GCCollectMode collectMode)93 void Collect(const GCObjectVisitor &gcObjectVisitor, GCCollectMode collectMode) final 94 { 95 (void)gcObjectVisitor; 96 (void)collectMode; 97 UNREACHABLE(); 98 } 99 100 /** 101 * Collect non regular regions (i.e. remove dead objects from Humongous and NonMovable regions 102 * and remove empty regions). 103 */ 104 void CollectNonRegularRegions(const RegionsVisitor ®ionVisitor, const GCObjectVisitor &gcObjectVisitor); 105 106 size_t GetRegularObjectMaxSize() final; 107 108 size_t GetLargeObjectMaxSize() final; 109 110 bool IsObjectInYoungSpace(const ObjectHeader *obj) final; 111 112 bool IsIntersectedWithYoung(const MemRange &memRange) final; 113 114 bool HasYoungSpace() final; 115 116 const std::vector<MemRange> &GetYoungSpaceMemRanges() final; 117 118 template <bool INCLUDE_CURRENT_REGION> GetTopGarbageRegions()119 PandaPriorityQueue<std::pair<uint32_t, Region *>> GetTopGarbageRegions() 120 { 121 return objectAllocator_->template GetTopGarbageRegions<INCLUDE_CURRENT_REGION>(); 122 } 123 124 std::vector<MarkBitmap *> &GetYoungSpaceBitmaps() final; 125 ReserveRegionIfNeeded()126 void ReserveRegionIfNeeded() 127 { 128 objectAllocator_->ReserveRegionIfNeeded(); 129 } 130 ReleaseReservedRegion()131 void ReleaseReservedRegion() 132 { 133 objectAllocator_->ReleaseReservedRegion(); 134 } 135 136 void ResetYoungAllocator() final; 137 138 template <RegionFlag REGIONS_TYPE, RegionSpace::ReleaseRegionsPolicy REGIONS_RELEASE_POLICY, 139 OSPagesPolicy OS_PAGES_POLICY, bool NEED_LOCK, typename Container> ResetRegions(const Container & regions)140 void ResetRegions(const Container ®ions) 141 { 142 objectAllocator_->ResetSeveralSpecificRegions<REGIONS_TYPE, REGIONS_RELEASE_POLICY, OS_PAGES_POLICY, NEED_LOCK>( 143 regions); 144 } 145 146 TLAB *CreateNewTLAB(panda::ManagedThread *thread) final; 147 148 size_t GetTLABMaxAllocSize() final; 149 IsTLABSupported()150 bool IsTLABSupported() final 151 { 152 return true; 153 } 154 155 void IterateOverObjectsInRange(MemRange memRange, const ObjectVisitor &objectVisitor) final; 156 157 bool ContainObject(const ObjectHeader *obj) const final; 158 159 bool IsLive(const ObjectHeader *obj) final; 160 VerifyAllocatorStatus()161 size_t VerifyAllocatorStatus() final 162 { 163 LOG(FATAL, ALLOC) << "Not implemented"; 164 return 0; 165 } 166 AllocateLocal(size_t size,Alignment align,panda::ManagedThread * thread)167 [[nodiscard]] void *AllocateLocal([[maybe_unused]] size_t size, [[maybe_unused]] Alignment align, 168 [[maybe_unused]] panda::ManagedThread *thread) final 169 { 170 LOG(FATAL, ALLOC) << "ObjectAllocatorGen: AllocateLocal not supported"; 171 return nullptr; 172 } 173 174 bool IsObjectInNonMovableSpace(const ObjectHeader *obj) final; 175 176 void UpdateSpaceData() final; 177 178 void CompactYoungRegions(const GCObjectVisitor &deathChecker, const ObjectVisitorEx &moveChecker); 179 180 template <RegionFlag REGION_TYPE, bool USE_MARKBITMAP = false> CompactRegion(Region * region,const GCObjectVisitor & deathChecker,const ObjectVisitorEx & moveChecker)181 void CompactRegion(Region *region, const GCObjectVisitor &deathChecker, const ObjectVisitorEx &moveChecker) 182 { 183 objectAllocator_->template CompactSpecificRegion<REGION_TYPE, RegionFlag::IS_OLD, USE_MARKBITMAP>( 184 region, deathChecker, moveChecker); 185 } 186 187 template <bool USE_MARKBITMAP> PromoteYoungRegion(Region * region,const GCObjectVisitor & deathChecker,const ObjectVisitor & promotionChecker)188 void PromoteYoungRegion(Region *region, const GCObjectVisitor &deathChecker, const ObjectVisitor &promotionChecker) 189 { 190 ASSERT(region->HasFlag(RegionFlag::IS_EDEN)); 191 objectAllocator_->template PromoteYoungRegion<USE_MARKBITMAP>(region, deathChecker, promotionChecker); 192 } 193 194 void CompactTenuredRegions(const PandaVector<Region *> ®ions, const GCObjectVisitor &deathChecker, 195 const ObjectVisitorEx &moveChecker); 196 ClearCurrentTenuredRegion()197 void ClearCurrentTenuredRegion() 198 { 199 objectAllocator_->template ClearCurrentRegion<IS_OLD>(); 200 } 201 GetRegionSize()202 static constexpr size_t GetRegionSize() 203 { 204 return REGION_SIZE; 205 } 206 HaveTenuredSize(size_t numRegions)207 bool HaveTenuredSize(size_t numRegions) const 208 { 209 return objectAllocator_->GetSpace()->GetPool()->HaveTenuredSize(numRegions * ObjectAllocator::REGION_SIZE); 210 } 211 HaveFreeRegions(size_t numRegions)212 bool HaveFreeRegions(size_t numRegions) const 213 { 214 return objectAllocator_->GetSpace()->GetPool()->HaveFreeRegions(numRegions, ObjectAllocator::REGION_SIZE); 215 } 216 GetYoungAllocMaxSize()217 static constexpr size_t GetYoungAllocMaxSize() 218 { 219 // NOTE(dtrubenkov): FIX to more meaningful value 220 return ObjectAllocator::GetMaxRegularObjectSize(); 221 } 222 223 template <RegionFlag REGION_TYPE, OSPagesPolicy OS_PAGES_POLICY> ReleaseEmptyRegions()224 void ReleaseEmptyRegions() 225 { 226 objectAllocator_->ReleaseEmptyRegions<REGION_TYPE, OS_PAGES_POLICY>(); 227 } 228 SetDesiredEdenLength(size_t edenLength)229 void SetDesiredEdenLength(size_t edenLength) 230 { 231 objectAllocator_->SetDesiredEdenLength(edenLength); 232 } 233 234 private: 235 Alignment CalculateAllocatorAlignment(size_t align) final; 236 237 PandaUniquePtr<ObjectAllocator> objectAllocator_ {nullptr}; 238 PandaUniquePtr<NonMovableAllocator> nonmovableAllocator_ {nullptr}; 239 PandaUniquePtr<HumongousObjectAllocator> humongousObjectAllocator_ {nullptr}; 240 MemStatsType *memStats_ {nullptr}; 241 242 void *AllocateTenured(size_t size) final; 243 244 void *AllocateTenuredWithoutLocks(size_t size) final; 245 246 friend class AllocTypeConfigG1; 247 }; 248 249 } // namespace panda::mem 250 251 #endif // RUNTIME_MEM_GC_G1_G1_ALLOCATOR_H 252