1*795d594fSAndroid Build Coastguard Worker /* 2*795d594fSAndroid Build Coastguard Worker * Copyright (C) 2014 The Android Open Source Project 3*795d594fSAndroid Build Coastguard Worker * 4*795d594fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 5*795d594fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 6*795d594fSAndroid Build Coastguard Worker * You may obtain a copy of the License at 7*795d594fSAndroid Build Coastguard Worker * 8*795d594fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 9*795d594fSAndroid Build Coastguard Worker * 10*795d594fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 11*795d594fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 12*795d594fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*795d594fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 14*795d594fSAndroid Build Coastguard Worker * limitations under the License. 15*795d594fSAndroid Build Coastguard Worker */ 16*795d594fSAndroid Build Coastguard Worker 17*795d594fSAndroid Build Coastguard Worker #ifndef ART_RUNTIME_GC_SPACE_REGION_SPACE_H_ 18*795d594fSAndroid Build Coastguard Worker #define ART_RUNTIME_GC_SPACE_REGION_SPACE_H_ 19*795d594fSAndroid Build Coastguard Worker 20*795d594fSAndroid Build Coastguard Worker #include "base/macros.h" 21*795d594fSAndroid Build Coastguard Worker #include "base/mutex.h" 22*795d594fSAndroid Build Coastguard Worker #include "space.h" 23*795d594fSAndroid Build Coastguard Worker #include "thread.h" 24*795d594fSAndroid Build Coastguard Worker 25*795d594fSAndroid Build Coastguard Worker #include <functional> 26*795d594fSAndroid Build Coastguard Worker #include <map> 27*795d594fSAndroid Build Coastguard Worker 28*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN { 29*795d594fSAndroid Build Coastguard Worker namespace gc { 30*795d594fSAndroid Build Coastguard Worker 31*795d594fSAndroid Build Coastguard Worker namespace accounting { 32*795d594fSAndroid Build Coastguard Worker class ReadBarrierTable; 33*795d594fSAndroid Build Coastguard Worker } // namespace accounting 34*795d594fSAndroid Build Coastguard Worker 35*795d594fSAndroid Build Coastguard Worker namespace space { 36*795d594fSAndroid Build Coastguard Worker 37*795d594fSAndroid Build Coastguard Worker // Cyclic region allocation strategy. If `true`, region allocation 38*795d594fSAndroid Build Coastguard Worker // will not try to allocate a new region from the beginning of the 39*795d594fSAndroid Build Coastguard Worker // region space, but from the last allocated region. This allocation 40*795d594fSAndroid Build Coastguard Worker // strategy reduces region reuse and should help catch some GC bugs 41*795d594fSAndroid Build Coastguard Worker // earlier. However, cyclic region allocation can also create memory 42*795d594fSAndroid Build Coastguard Worker // fragmentation at the region level (see b/33795328); therefore, we 43*795d594fSAndroid Build Coastguard Worker // only enable it in debug mode. 44*795d594fSAndroid Build Coastguard Worker static constexpr bool kCyclicRegionAllocation = kIsDebugBuild; 45*795d594fSAndroid Build Coastguard Worker 46*795d594fSAndroid Build Coastguard Worker // A space that consists of equal-sized regions. 47*795d594fSAndroid Build Coastguard Worker class RegionSpace final : public ContinuousMemMapAllocSpace { 48*795d594fSAndroid Build Coastguard Worker public: 49*795d594fSAndroid Build Coastguard Worker using WalkCallback = void (*)(void *start, void *end, size_t num_bytes, void* callback_arg); 50*795d594fSAndroid Build Coastguard Worker 51*795d594fSAndroid Build Coastguard Worker enum EvacMode { 52*795d594fSAndroid Build Coastguard Worker kEvacModeNewlyAllocated, 53*795d594fSAndroid Build Coastguard Worker kEvacModeLivePercentNewlyAllocated, 54*795d594fSAndroid Build Coastguard Worker kEvacModeForceAll, 55*795d594fSAndroid Build Coastguard Worker }; 56*795d594fSAndroid Build Coastguard Worker GetType()57*795d594fSAndroid Build Coastguard Worker SpaceType GetType() const override { 58*795d594fSAndroid Build Coastguard Worker return kSpaceTypeRegionSpace; 59*795d594fSAndroid Build Coastguard Worker } 60*795d594fSAndroid Build Coastguard Worker 61*795d594fSAndroid Build Coastguard Worker // Create a region space mem map with the requested sizes. The requested base address is not 62*795d594fSAndroid Build Coastguard Worker // guaranteed to be granted, if it is required, the caller should call Begin on the returned 63*795d594fSAndroid Build Coastguard Worker // space to confirm the request was granted. 64*795d594fSAndroid Build Coastguard Worker static MemMap CreateMemMap(const std::string& name, size_t capacity, uint8_t* requested_begin); 65*795d594fSAndroid Build Coastguard Worker static RegionSpace* Create(const std::string& name, MemMap&& mem_map, bool use_generational_cc); 66*795d594fSAndroid Build Coastguard Worker 67*795d594fSAndroid Build Coastguard Worker // Allocate `num_bytes`, returns null if the space is full. 68*795d594fSAndroid Build Coastguard Worker mirror::Object* Alloc(Thread* self, 69*795d594fSAndroid Build Coastguard Worker size_t num_bytes, 70*795d594fSAndroid Build Coastguard Worker /* out */ size_t* bytes_allocated, 71*795d594fSAndroid Build Coastguard Worker /* out */ size_t* usable_size, 72*795d594fSAndroid Build Coastguard Worker /* out */ size_t* bytes_tl_bulk_allocated) 73*795d594fSAndroid Build Coastguard Worker override REQUIRES(!region_lock_); 74*795d594fSAndroid Build Coastguard Worker // Thread-unsafe allocation for when mutators are suspended, used by the semispace collector. 75*795d594fSAndroid Build Coastguard Worker mirror::Object* AllocThreadUnsafe(Thread* self, 76*795d594fSAndroid Build Coastguard Worker size_t num_bytes, 77*795d594fSAndroid Build Coastguard Worker /* out */ size_t* bytes_allocated, 78*795d594fSAndroid Build Coastguard Worker /* out */ size_t* usable_size, 79*795d594fSAndroid Build Coastguard Worker /* out */ size_t* bytes_tl_bulk_allocated) 80*795d594fSAndroid Build Coastguard Worker override REQUIRES(Locks::mutator_lock_) REQUIRES(!region_lock_); 81*795d594fSAndroid Build Coastguard Worker // The main allocation routine. 82*795d594fSAndroid Build Coastguard Worker template<bool kForEvac> 83*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE mirror::Object* AllocNonvirtual(size_t num_bytes, 84*795d594fSAndroid Build Coastguard Worker /* out */ size_t* bytes_allocated, 85*795d594fSAndroid Build Coastguard Worker /* out */ size_t* usable_size, 86*795d594fSAndroid Build Coastguard Worker /* out */ size_t* bytes_tl_bulk_allocated) 87*795d594fSAndroid Build Coastguard Worker REQUIRES(!region_lock_); 88*795d594fSAndroid Build Coastguard Worker // Allocate/free large objects (objects that are larger than the region size). 89*795d594fSAndroid Build Coastguard Worker template<bool kForEvac> 90*795d594fSAndroid Build Coastguard Worker mirror::Object* AllocLarge(size_t num_bytes, 91*795d594fSAndroid Build Coastguard Worker /* out */ size_t* bytes_allocated, 92*795d594fSAndroid Build Coastguard Worker /* out */ size_t* usable_size, 93*795d594fSAndroid Build Coastguard Worker /* out */ size_t* bytes_tl_bulk_allocated) REQUIRES(!region_lock_); 94*795d594fSAndroid Build Coastguard Worker template<bool kForEvac> 95*795d594fSAndroid Build Coastguard Worker void FreeLarge(mirror::Object* large_obj, size_t bytes_allocated) REQUIRES(!region_lock_); 96*795d594fSAndroid Build Coastguard Worker 97*795d594fSAndroid Build Coastguard Worker // Return the storage space required by obj. AllocationSize(mirror::Object * obj,size_t * usable_size)98*795d594fSAndroid Build Coastguard Worker size_t AllocationSize(mirror::Object* obj, size_t* usable_size) override 99*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!region_lock_) { 100*795d594fSAndroid Build Coastguard Worker return AllocationSizeNonvirtual(obj, usable_size); 101*795d594fSAndroid Build Coastguard Worker } 102*795d594fSAndroid Build Coastguard Worker EXPORT size_t AllocationSizeNonvirtual(mirror::Object* obj, size_t* usable_size) 103*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!region_lock_); 104*795d594fSAndroid Build Coastguard Worker Free(Thread *,mirror::Object *)105*795d594fSAndroid Build Coastguard Worker size_t Free(Thread*, mirror::Object*) override { 106*795d594fSAndroid Build Coastguard Worker UNIMPLEMENTED(FATAL); 107*795d594fSAndroid Build Coastguard Worker return 0; 108*795d594fSAndroid Build Coastguard Worker } FreeList(Thread *,size_t,mirror::Object **)109*795d594fSAndroid Build Coastguard Worker size_t FreeList(Thread*, size_t, mirror::Object**) override { 110*795d594fSAndroid Build Coastguard Worker UNIMPLEMENTED(FATAL); 111*795d594fSAndroid Build Coastguard Worker return 0; 112*795d594fSAndroid Build Coastguard Worker } GetLiveBitmap()113*795d594fSAndroid Build Coastguard Worker accounting::ContinuousSpaceBitmap* GetLiveBitmap() override { 114*795d594fSAndroid Build Coastguard Worker return &mark_bitmap_; 115*795d594fSAndroid Build Coastguard Worker } GetMarkBitmap()116*795d594fSAndroid Build Coastguard Worker accounting::ContinuousSpaceBitmap* GetMarkBitmap() override { 117*795d594fSAndroid Build Coastguard Worker return &mark_bitmap_; 118*795d594fSAndroid Build Coastguard Worker } 119*795d594fSAndroid Build Coastguard Worker 120*795d594fSAndroid Build Coastguard Worker EXPORT void Clear() override REQUIRES(!region_lock_); 121*795d594fSAndroid Build Coastguard Worker 122*795d594fSAndroid Build Coastguard Worker // Remove read and write memory protection from the whole region space, 123*795d594fSAndroid Build Coastguard Worker // i.e. make memory pages backing the region area not readable and not 124*795d594fSAndroid Build Coastguard Worker // writable. 125*795d594fSAndroid Build Coastguard Worker void Protect(); 126*795d594fSAndroid Build Coastguard Worker 127*795d594fSAndroid Build Coastguard Worker // Remove memory protection from the whole region space, i.e. make memory 128*795d594fSAndroid Build Coastguard Worker // pages backing the region area readable and writable. This method is useful 129*795d594fSAndroid Build Coastguard Worker // to avoid page protection faults when dumping information about an invalid 130*795d594fSAndroid Build Coastguard Worker // reference. 131*795d594fSAndroid Build Coastguard Worker EXPORT void Unprotect(); 132*795d594fSAndroid Build Coastguard Worker 133*795d594fSAndroid Build Coastguard Worker // Change the non growth limit capacity to new capacity by shrinking or expanding the map. 134*795d594fSAndroid Build Coastguard Worker // Currently, only shrinking is supported. 135*795d594fSAndroid Build Coastguard Worker // Unlike implementations of this function in other spaces, we need to pass 136*795d594fSAndroid Build Coastguard Worker // new capacity as argument here as region space doesn't have any notion of 137*795d594fSAndroid Build Coastguard Worker // growth limit. 138*795d594fSAndroid Build Coastguard Worker void ClampGrowthLimit(size_t new_capacity) REQUIRES(!region_lock_); 139*795d594fSAndroid Build Coastguard Worker 140*795d594fSAndroid Build Coastguard Worker EXPORT void Dump(std::ostream& os) const override; 141*795d594fSAndroid Build Coastguard Worker void DumpRegions(std::ostream& os) REQUIRES(!region_lock_); 142*795d594fSAndroid Build Coastguard Worker // Dump region containing object `obj`. Precondition: `obj` is in the region space. 143*795d594fSAndroid Build Coastguard Worker void DumpRegionForObject(std::ostream& os, mirror::Object* obj) REQUIRES(!region_lock_); 144*795d594fSAndroid Build Coastguard Worker EXPORT void DumpNonFreeRegions(std::ostream& os) REQUIRES(!region_lock_); 145*795d594fSAndroid Build Coastguard Worker 146*795d594fSAndroid Build Coastguard Worker EXPORT size_t RevokeThreadLocalBuffers(Thread* thread) override REQUIRES(!region_lock_); 147*795d594fSAndroid Build Coastguard Worker size_t RevokeThreadLocalBuffers(Thread* thread, const bool reuse) REQUIRES(!region_lock_); 148*795d594fSAndroid Build Coastguard Worker EXPORT size_t RevokeAllThreadLocalBuffers() override 149*795d594fSAndroid Build Coastguard Worker REQUIRES(!Locks::runtime_shutdown_lock_, !Locks::thread_list_lock_, !region_lock_); 150*795d594fSAndroid Build Coastguard Worker void AssertThreadLocalBuffersAreRevoked(Thread* thread) REQUIRES(!region_lock_); 151*795d594fSAndroid Build Coastguard Worker void AssertAllThreadLocalBuffersAreRevoked() 152*795d594fSAndroid Build Coastguard Worker REQUIRES(!Locks::runtime_shutdown_lock_, !Locks::thread_list_lock_, !region_lock_); 153*795d594fSAndroid Build Coastguard Worker 154*795d594fSAndroid Build Coastguard Worker enum class RegionType : uint8_t { 155*795d594fSAndroid Build Coastguard Worker kRegionTypeAll, // All types. 156*795d594fSAndroid Build Coastguard Worker kRegionTypeFromSpace, // From-space. To be evacuated. 157*795d594fSAndroid Build Coastguard Worker kRegionTypeUnevacFromSpace, // Unevacuated from-space. Not to be evacuated. 158*795d594fSAndroid Build Coastguard Worker kRegionTypeToSpace, // To-space. 159*795d594fSAndroid Build Coastguard Worker kRegionTypeNone, // None. 160*795d594fSAndroid Build Coastguard Worker }; 161*795d594fSAndroid Build Coastguard Worker 162*795d594fSAndroid Build Coastguard Worker enum class RegionState : uint8_t { 163*795d594fSAndroid Build Coastguard Worker kRegionStateFree, // Free region. 164*795d594fSAndroid Build Coastguard Worker kRegionStateAllocated, // Allocated region. 165*795d594fSAndroid Build Coastguard Worker kRegionStateLarge, // Large allocated (allocation larger than the region size). 166*795d594fSAndroid Build Coastguard Worker kRegionStateLargeTail, // Large tail (non-first regions of a large allocation). 167*795d594fSAndroid Build Coastguard Worker }; 168*795d594fSAndroid Build Coastguard Worker 169*795d594fSAndroid Build Coastguard Worker template<RegionType kRegionType> uint64_t GetBytesAllocatedInternal() REQUIRES(!region_lock_); 170*795d594fSAndroid Build Coastguard Worker template<RegionType kRegionType> uint64_t GetObjectsAllocatedInternal() REQUIRES(!region_lock_); GetBytesAllocated()171*795d594fSAndroid Build Coastguard Worker uint64_t GetBytesAllocated() override REQUIRES(!region_lock_) { 172*795d594fSAndroid Build Coastguard Worker return GetBytesAllocatedInternal<RegionType::kRegionTypeAll>(); 173*795d594fSAndroid Build Coastguard Worker } GetObjectsAllocated()174*795d594fSAndroid Build Coastguard Worker uint64_t GetObjectsAllocated() override REQUIRES(!region_lock_) { 175*795d594fSAndroid Build Coastguard Worker return GetObjectsAllocatedInternal<RegionType::kRegionTypeAll>(); 176*795d594fSAndroid Build Coastguard Worker } GetBytesAllocatedInFromSpace()177*795d594fSAndroid Build Coastguard Worker uint64_t GetBytesAllocatedInFromSpace() REQUIRES(!region_lock_) { 178*795d594fSAndroid Build Coastguard Worker return GetBytesAllocatedInternal<RegionType::kRegionTypeFromSpace>(); 179*795d594fSAndroid Build Coastguard Worker } GetObjectsAllocatedInFromSpace()180*795d594fSAndroid Build Coastguard Worker uint64_t GetObjectsAllocatedInFromSpace() REQUIRES(!region_lock_) { 181*795d594fSAndroid Build Coastguard Worker return GetObjectsAllocatedInternal<RegionType::kRegionTypeFromSpace>(); 182*795d594fSAndroid Build Coastguard Worker } GetBytesAllocatedInUnevacFromSpace()183*795d594fSAndroid Build Coastguard Worker uint64_t GetBytesAllocatedInUnevacFromSpace() REQUIRES(!region_lock_) { 184*795d594fSAndroid Build Coastguard Worker return GetBytesAllocatedInternal<RegionType::kRegionTypeUnevacFromSpace>(); 185*795d594fSAndroid Build Coastguard Worker } GetObjectsAllocatedInUnevacFromSpace()186*795d594fSAndroid Build Coastguard Worker uint64_t GetObjectsAllocatedInUnevacFromSpace() REQUIRES(!region_lock_) { 187*795d594fSAndroid Build Coastguard Worker return GetObjectsAllocatedInternal<RegionType::kRegionTypeUnevacFromSpace>(); 188*795d594fSAndroid Build Coastguard Worker } GetMaxPeakNumNonFreeRegions()189*795d594fSAndroid Build Coastguard Worker size_t GetMaxPeakNumNonFreeRegions() const { 190*795d594fSAndroid Build Coastguard Worker return max_peak_num_non_free_regions_; 191*795d594fSAndroid Build Coastguard Worker } GetNumRegions()192*795d594fSAndroid Build Coastguard Worker size_t GetNumRegions() const { 193*795d594fSAndroid Build Coastguard Worker return num_regions_; 194*795d594fSAndroid Build Coastguard Worker } GetNumNonFreeRegions()195*795d594fSAndroid Build Coastguard Worker size_t GetNumNonFreeRegions() const NO_THREAD_SAFETY_ANALYSIS { 196*795d594fSAndroid Build Coastguard Worker return num_non_free_regions_; 197*795d594fSAndroid Build Coastguard Worker } 198*795d594fSAndroid Build Coastguard Worker CanMoveObjects()199*795d594fSAndroid Build Coastguard Worker bool CanMoveObjects() const override { 200*795d594fSAndroid Build Coastguard Worker return true; 201*795d594fSAndroid Build Coastguard Worker } 202*795d594fSAndroid Build Coastguard Worker Contains(const mirror::Object * obj)203*795d594fSAndroid Build Coastguard Worker bool Contains(const mirror::Object* obj) const override { 204*795d594fSAndroid Build Coastguard Worker const uint8_t* byte_obj = reinterpret_cast<const uint8_t*>(obj); 205*795d594fSAndroid Build Coastguard Worker return byte_obj >= Begin() && byte_obj < Limit(); 206*795d594fSAndroid Build Coastguard Worker } 207*795d594fSAndroid Build Coastguard Worker AsRegionSpace()208*795d594fSAndroid Build Coastguard Worker RegionSpace* AsRegionSpace() override { 209*795d594fSAndroid Build Coastguard Worker return this; 210*795d594fSAndroid Build Coastguard Worker } 211*795d594fSAndroid Build Coastguard Worker 212*795d594fSAndroid Build Coastguard Worker // Go through all of the blocks and visit the continuous objects. 213*795d594fSAndroid Build Coastguard Worker template <typename Visitor> 214*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE void Walk(Visitor&& visitor) REQUIRES(Locks::mutator_lock_); 215*795d594fSAndroid Build Coastguard Worker template <typename Visitor> 216*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE void WalkToSpace(Visitor&& visitor) REQUIRES(Locks::mutator_lock_); 217*795d594fSAndroid Build Coastguard Worker 218*795d594fSAndroid Build Coastguard Worker // Scans regions and calls visitor for objects in unevac-space corresponding 219*795d594fSAndroid Build Coastguard Worker // to the bits set in 'bitmap'. 220*795d594fSAndroid Build Coastguard Worker // Cannot acquire region_lock_ as visitor may need to acquire it for allocation. 221*795d594fSAndroid Build Coastguard Worker // Should not be called concurrently with functions (like SetFromSpace()) which 222*795d594fSAndroid Build Coastguard Worker // change regions' type. 223*795d594fSAndroid Build Coastguard Worker template <typename Visitor> 224*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE void ScanUnevacFromSpace(accounting::ContinuousSpaceBitmap* bitmap, 225*795d594fSAndroid Build Coastguard Worker Visitor&& visitor) NO_THREAD_SAFETY_ANALYSIS; 226*795d594fSAndroid Build Coastguard Worker GetSweepCallback()227*795d594fSAndroid Build Coastguard Worker accounting::ContinuousSpaceBitmap::SweepCallback* GetSweepCallback() override { 228*795d594fSAndroid Build Coastguard Worker return nullptr; 229*795d594fSAndroid Build Coastguard Worker } 230*795d594fSAndroid Build Coastguard Worker EXPORT bool LogFragmentationAllocFailure(std::ostream& os, size_t failed_alloc_bytes) override 231*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!region_lock_); 232*795d594fSAndroid Build Coastguard Worker 233*795d594fSAndroid Build Coastguard Worker // Object alignment within the space. 234*795d594fSAndroid Build Coastguard Worker static constexpr size_t kAlignment = kObjectAlignment; 235*795d594fSAndroid Build Coastguard Worker // The region size. 236*795d594fSAndroid Build Coastguard Worker static constexpr size_t kRegionSize = 256 * KB; 237*795d594fSAndroid Build Coastguard Worker IsInFromSpace(mirror::Object * ref)238*795d594fSAndroid Build Coastguard Worker bool IsInFromSpace(mirror::Object* ref) { 239*795d594fSAndroid Build Coastguard Worker if (HasAddress(ref)) { 240*795d594fSAndroid Build Coastguard Worker Region* r = RefToRegionUnlocked(ref); 241*795d594fSAndroid Build Coastguard Worker return r->IsInFromSpace(); 242*795d594fSAndroid Build Coastguard Worker } 243*795d594fSAndroid Build Coastguard Worker return false; 244*795d594fSAndroid Build Coastguard Worker } 245*795d594fSAndroid Build Coastguard Worker IsRegionNewlyAllocated(size_t idx)246*795d594fSAndroid Build Coastguard Worker bool IsRegionNewlyAllocated(size_t idx) const NO_THREAD_SAFETY_ANALYSIS { 247*795d594fSAndroid Build Coastguard Worker DCHECK_LT(idx, num_regions_); 248*795d594fSAndroid Build Coastguard Worker return regions_[idx].IsNewlyAllocated(); 249*795d594fSAndroid Build Coastguard Worker } 250*795d594fSAndroid Build Coastguard Worker IsInNewlyAllocatedRegion(mirror::Object * ref)251*795d594fSAndroid Build Coastguard Worker bool IsInNewlyAllocatedRegion(mirror::Object* ref) { 252*795d594fSAndroid Build Coastguard Worker if (HasAddress(ref)) { 253*795d594fSAndroid Build Coastguard Worker Region* r = RefToRegionUnlocked(ref); 254*795d594fSAndroid Build Coastguard Worker return r->IsNewlyAllocated(); 255*795d594fSAndroid Build Coastguard Worker } 256*795d594fSAndroid Build Coastguard Worker return false; 257*795d594fSAndroid Build Coastguard Worker } 258*795d594fSAndroid Build Coastguard Worker IsInUnevacFromSpace(mirror::Object * ref)259*795d594fSAndroid Build Coastguard Worker bool IsInUnevacFromSpace(mirror::Object* ref) { 260*795d594fSAndroid Build Coastguard Worker if (HasAddress(ref)) { 261*795d594fSAndroid Build Coastguard Worker Region* r = RefToRegionUnlocked(ref); 262*795d594fSAndroid Build Coastguard Worker return r->IsInUnevacFromSpace(); 263*795d594fSAndroid Build Coastguard Worker } 264*795d594fSAndroid Build Coastguard Worker return false; 265*795d594fSAndroid Build Coastguard Worker } 266*795d594fSAndroid Build Coastguard Worker IsLargeObject(mirror::Object * ref)267*795d594fSAndroid Build Coastguard Worker bool IsLargeObject(mirror::Object* ref) { 268*795d594fSAndroid Build Coastguard Worker if (HasAddress(ref)) { 269*795d594fSAndroid Build Coastguard Worker Region* r = RefToRegionUnlocked(ref); 270*795d594fSAndroid Build Coastguard Worker return r->IsLarge(); 271*795d594fSAndroid Build Coastguard Worker } 272*795d594fSAndroid Build Coastguard Worker return false; 273*795d594fSAndroid Build Coastguard Worker } 274*795d594fSAndroid Build Coastguard Worker IsInToSpace(mirror::Object * ref)275*795d594fSAndroid Build Coastguard Worker bool IsInToSpace(mirror::Object* ref) { 276*795d594fSAndroid Build Coastguard Worker if (HasAddress(ref)) { 277*795d594fSAndroid Build Coastguard Worker Region* r = RefToRegionUnlocked(ref); 278*795d594fSAndroid Build Coastguard Worker return r->IsInToSpace(); 279*795d594fSAndroid Build Coastguard Worker } 280*795d594fSAndroid Build Coastguard Worker return false; 281*795d594fSAndroid Build Coastguard Worker } 282*795d594fSAndroid Build Coastguard Worker 283*795d594fSAndroid Build Coastguard Worker // If `ref` is in the region space, return the type of its region; 284*795d594fSAndroid Build Coastguard Worker // otherwise, return `RegionType::kRegionTypeNone`. GetRegionType(mirror::Object * ref)285*795d594fSAndroid Build Coastguard Worker RegionType GetRegionType(mirror::Object* ref) { 286*795d594fSAndroid Build Coastguard Worker if (HasAddress(ref)) { 287*795d594fSAndroid Build Coastguard Worker return GetRegionTypeUnsafe(ref); 288*795d594fSAndroid Build Coastguard Worker } 289*795d594fSAndroid Build Coastguard Worker return RegionType::kRegionTypeNone; 290*795d594fSAndroid Build Coastguard Worker } 291*795d594fSAndroid Build Coastguard Worker 292*795d594fSAndroid Build Coastguard Worker // Unsafe version of RegionSpace::GetRegionType. 293*795d594fSAndroid Build Coastguard Worker // Precondition: `ref` is in the region space. GetRegionTypeUnsafe(mirror::Object * ref)294*795d594fSAndroid Build Coastguard Worker RegionType GetRegionTypeUnsafe(mirror::Object* ref) { 295*795d594fSAndroid Build Coastguard Worker DCHECK(HasAddress(ref)) << ref; 296*795d594fSAndroid Build Coastguard Worker Region* r = RefToRegionUnlocked(ref); 297*795d594fSAndroid Build Coastguard Worker return r->Type(); 298*795d594fSAndroid Build Coastguard Worker } 299*795d594fSAndroid Build Coastguard Worker 300*795d594fSAndroid Build Coastguard Worker // Zero live bytes for a large object, used by young gen CC for marking newly allocated large 301*795d594fSAndroid Build Coastguard Worker // objects. 302*795d594fSAndroid Build Coastguard Worker void ZeroLiveBytesForLargeObject(mirror::Object* obj) REQUIRES_SHARED(Locks::mutator_lock_); 303*795d594fSAndroid Build Coastguard Worker 304*795d594fSAndroid Build Coastguard Worker // Determine which regions to evacuate and tag them as 305*795d594fSAndroid Build Coastguard Worker // from-space. Tag the rest as unevacuated from-space. 306*795d594fSAndroid Build Coastguard Worker void SetFromSpace(accounting::ReadBarrierTable* rb_table, 307*795d594fSAndroid Build Coastguard Worker EvacMode evac_mode, 308*795d594fSAndroid Build Coastguard Worker bool clear_live_bytes) 309*795d594fSAndroid Build Coastguard Worker REQUIRES(!region_lock_); 310*795d594fSAndroid Build Coastguard Worker 311*795d594fSAndroid Build Coastguard Worker size_t FromSpaceSize() REQUIRES(!region_lock_); 312*795d594fSAndroid Build Coastguard Worker size_t UnevacFromSpaceSize() REQUIRES(!region_lock_); 313*795d594fSAndroid Build Coastguard Worker size_t ToSpaceSize() REQUIRES(!region_lock_); 314*795d594fSAndroid Build Coastguard Worker void ClearFromSpace(/* out */ uint64_t* cleared_bytes, 315*795d594fSAndroid Build Coastguard Worker /* out */ uint64_t* cleared_objects, 316*795d594fSAndroid Build Coastguard Worker const bool clear_bitmap, 317*795d594fSAndroid Build Coastguard Worker const bool release_eagerly) 318*795d594fSAndroid Build Coastguard Worker REQUIRES(!region_lock_); 319*795d594fSAndroid Build Coastguard Worker AddLiveBytes(mirror::Object * ref,size_t alloc_size)320*795d594fSAndroid Build Coastguard Worker void AddLiveBytes(mirror::Object* ref, size_t alloc_size) { 321*795d594fSAndroid Build Coastguard Worker Region* reg = RefToRegionUnlocked(ref); 322*795d594fSAndroid Build Coastguard Worker reg->AddLiveBytes(alloc_size); 323*795d594fSAndroid Build Coastguard Worker } 324*795d594fSAndroid Build Coastguard Worker AssertAllRegionLiveBytesZeroOrCleared()325*795d594fSAndroid Build Coastguard Worker void AssertAllRegionLiveBytesZeroOrCleared() REQUIRES(!region_lock_) { 326*795d594fSAndroid Build Coastguard Worker if (kIsDebugBuild) { 327*795d594fSAndroid Build Coastguard Worker MutexLock mu(Thread::Current(), region_lock_); 328*795d594fSAndroid Build Coastguard Worker for (size_t i = 0; i < num_regions_; ++i) { 329*795d594fSAndroid Build Coastguard Worker Region* r = ®ions_[i]; 330*795d594fSAndroid Build Coastguard Worker size_t live_bytes = r->LiveBytes(); 331*795d594fSAndroid Build Coastguard Worker CHECK(live_bytes == 0U || live_bytes == static_cast<size_t>(-1)) << live_bytes; 332*795d594fSAndroid Build Coastguard Worker } 333*795d594fSAndroid Build Coastguard Worker } 334*795d594fSAndroid Build Coastguard Worker } 335*795d594fSAndroid Build Coastguard Worker SetAllRegionLiveBytesZero()336*795d594fSAndroid Build Coastguard Worker void SetAllRegionLiveBytesZero() REQUIRES(!region_lock_) { 337*795d594fSAndroid Build Coastguard Worker MutexLock mu(Thread::Current(), region_lock_); 338*795d594fSAndroid Build Coastguard Worker const size_t iter_limit = kUseTableLookupReadBarrier 339*795d594fSAndroid Build Coastguard Worker ? num_regions_ 340*795d594fSAndroid Build Coastguard Worker : std::min(num_regions_, non_free_region_index_limit_); 341*795d594fSAndroid Build Coastguard Worker for (size_t i = 0; i < iter_limit; ++i) { 342*795d594fSAndroid Build Coastguard Worker Region* r = ®ions_[i]; 343*795d594fSAndroid Build Coastguard Worker // Newly allocated regions don't need up-to-date live_bytes_ for deciding 344*795d594fSAndroid Build Coastguard Worker // whether to be evacuated or not. See Region::ShouldBeEvacuated(). 345*795d594fSAndroid Build Coastguard Worker if (!r->IsFree() && !r->IsNewlyAllocated()) { 346*795d594fSAndroid Build Coastguard Worker r->ZeroLiveBytes(); 347*795d594fSAndroid Build Coastguard Worker } 348*795d594fSAndroid Build Coastguard Worker } 349*795d594fSAndroid Build Coastguard Worker } 350*795d594fSAndroid Build Coastguard Worker RegionIdxForRefUnchecked(mirror::Object * ref)351*795d594fSAndroid Build Coastguard Worker size_t RegionIdxForRefUnchecked(mirror::Object* ref) const NO_THREAD_SAFETY_ANALYSIS { 352*795d594fSAndroid Build Coastguard Worker DCHECK(HasAddress(ref)); 353*795d594fSAndroid Build Coastguard Worker uintptr_t offset = reinterpret_cast<uintptr_t>(ref) - reinterpret_cast<uintptr_t>(Begin()); 354*795d594fSAndroid Build Coastguard Worker size_t reg_idx = offset / kRegionSize; 355*795d594fSAndroid Build Coastguard Worker DCHECK_LT(reg_idx, num_regions_); 356*795d594fSAndroid Build Coastguard Worker Region* reg = ®ions_[reg_idx]; 357*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(reg->Idx(), reg_idx); 358*795d594fSAndroid Build Coastguard Worker DCHECK(reg->Contains(ref)); 359*795d594fSAndroid Build Coastguard Worker return reg_idx; 360*795d594fSAndroid Build Coastguard Worker } 361*795d594fSAndroid Build Coastguard Worker // Return -1 as region index for references outside this region space. RegionIdxForRef(mirror::Object * ref)362*795d594fSAndroid Build Coastguard Worker size_t RegionIdxForRef(mirror::Object* ref) const NO_THREAD_SAFETY_ANALYSIS { 363*795d594fSAndroid Build Coastguard Worker if (HasAddress(ref)) { 364*795d594fSAndroid Build Coastguard Worker return RegionIdxForRefUnchecked(ref); 365*795d594fSAndroid Build Coastguard Worker } else { 366*795d594fSAndroid Build Coastguard Worker return static_cast<size_t>(-1); 367*795d594fSAndroid Build Coastguard Worker } 368*795d594fSAndroid Build Coastguard Worker } 369*795d594fSAndroid Build Coastguard Worker 370*795d594fSAndroid Build Coastguard Worker // Increment object allocation count for region containing ref. 371*795d594fSAndroid Build Coastguard Worker void RecordAlloc(mirror::Object* ref) REQUIRES(!region_lock_); 372*795d594fSAndroid Build Coastguard Worker 373*795d594fSAndroid Build Coastguard Worker bool AllocNewTlab(Thread* self, const size_t tlab_size, size_t* bytes_tl_bulk_allocated) 374*795d594fSAndroid Build Coastguard Worker REQUIRES(!region_lock_); 375*795d594fSAndroid Build Coastguard Worker Time()376*795d594fSAndroid Build Coastguard Worker uint32_t Time() { 377*795d594fSAndroid Build Coastguard Worker return time_; 378*795d594fSAndroid Build Coastguard Worker } 379*795d594fSAndroid Build Coastguard Worker EvacBytes()380*795d594fSAndroid Build Coastguard Worker size_t EvacBytes() const NO_THREAD_SAFETY_ANALYSIS { 381*795d594fSAndroid Build Coastguard Worker return num_evac_regions_ * kRegionSize; 382*795d594fSAndroid Build Coastguard Worker } 383*795d594fSAndroid Build Coastguard Worker GetMadviseTime()384*795d594fSAndroid Build Coastguard Worker uint64_t GetMadviseTime() const { 385*795d594fSAndroid Build Coastguard Worker return madvise_time_; 386*795d594fSAndroid Build Coastguard Worker } 387*795d594fSAndroid Build Coastguard Worker 388*795d594fSAndroid Build Coastguard Worker void ReleaseFreeRegions(); 389*795d594fSAndroid Build Coastguard Worker 390*795d594fSAndroid Build Coastguard Worker private: 391*795d594fSAndroid Build Coastguard Worker RegionSpace(const std::string& name, MemMap&& mem_map, bool use_generational_cc); 392*795d594fSAndroid Build Coastguard Worker 393*795d594fSAndroid Build Coastguard Worker class Region { 394*795d594fSAndroid Build Coastguard Worker public: Region()395*795d594fSAndroid Build Coastguard Worker Region() 396*795d594fSAndroid Build Coastguard Worker : idx_(static_cast<size_t>(-1)), 397*795d594fSAndroid Build Coastguard Worker live_bytes_(static_cast<size_t>(-1)), 398*795d594fSAndroid Build Coastguard Worker begin_(nullptr), 399*795d594fSAndroid Build Coastguard Worker thread_(nullptr), 400*795d594fSAndroid Build Coastguard Worker top_(nullptr), 401*795d594fSAndroid Build Coastguard Worker end_(nullptr), 402*795d594fSAndroid Build Coastguard Worker objects_allocated_(0), 403*795d594fSAndroid Build Coastguard Worker alloc_time_(0), 404*795d594fSAndroid Build Coastguard Worker is_newly_allocated_(false), 405*795d594fSAndroid Build Coastguard Worker is_a_tlab_(false), 406*795d594fSAndroid Build Coastguard Worker state_(RegionState::kRegionStateAllocated), 407*795d594fSAndroid Build Coastguard Worker type_(RegionType::kRegionTypeToSpace) {} 408*795d594fSAndroid Build Coastguard Worker Init(size_t idx,uint8_t * begin,uint8_t * end)409*795d594fSAndroid Build Coastguard Worker void Init(size_t idx, uint8_t* begin, uint8_t* end) { 410*795d594fSAndroid Build Coastguard Worker idx_ = idx; 411*795d594fSAndroid Build Coastguard Worker begin_ = begin; 412*795d594fSAndroid Build Coastguard Worker top_.store(begin, std::memory_order_relaxed); 413*795d594fSAndroid Build Coastguard Worker end_ = end; 414*795d594fSAndroid Build Coastguard Worker state_ = RegionState::kRegionStateFree; 415*795d594fSAndroid Build Coastguard Worker type_ = RegionType::kRegionTypeNone; 416*795d594fSAndroid Build Coastguard Worker objects_allocated_.store(0, std::memory_order_relaxed); 417*795d594fSAndroid Build Coastguard Worker alloc_time_ = 0; 418*795d594fSAndroid Build Coastguard Worker live_bytes_ = static_cast<size_t>(-1); 419*795d594fSAndroid Build Coastguard Worker is_newly_allocated_ = false; 420*795d594fSAndroid Build Coastguard Worker is_a_tlab_ = false; 421*795d594fSAndroid Build Coastguard Worker thread_ = nullptr; 422*795d594fSAndroid Build Coastguard Worker DCHECK_LT(begin, end); 423*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(static_cast<size_t>(end - begin), kRegionSize); 424*795d594fSAndroid Build Coastguard Worker } 425*795d594fSAndroid Build Coastguard Worker State()426*795d594fSAndroid Build Coastguard Worker RegionState State() const { 427*795d594fSAndroid Build Coastguard Worker return state_; 428*795d594fSAndroid Build Coastguard Worker } 429*795d594fSAndroid Build Coastguard Worker Type()430*795d594fSAndroid Build Coastguard Worker RegionType Type() const { 431*795d594fSAndroid Build Coastguard Worker return type_; 432*795d594fSAndroid Build Coastguard Worker } 433*795d594fSAndroid Build Coastguard Worker 434*795d594fSAndroid Build Coastguard Worker void Clear(bool zero_and_release_pages); 435*795d594fSAndroid Build Coastguard Worker 436*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE mirror::Object* Alloc(size_t num_bytes, 437*795d594fSAndroid Build Coastguard Worker /* out */ size_t* bytes_allocated, 438*795d594fSAndroid Build Coastguard Worker /* out */ size_t* usable_size, 439*795d594fSAndroid Build Coastguard Worker /* out */ size_t* bytes_tl_bulk_allocated); 440*795d594fSAndroid Build Coastguard Worker IsFree()441*795d594fSAndroid Build Coastguard Worker bool IsFree() const { 442*795d594fSAndroid Build Coastguard Worker bool is_free = (state_ == RegionState::kRegionStateFree); 443*795d594fSAndroid Build Coastguard Worker if (is_free) { 444*795d594fSAndroid Build Coastguard Worker DCHECK(IsInNoSpace()); 445*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(begin_, Top()); 446*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(objects_allocated_.load(std::memory_order_relaxed), 0U); 447*795d594fSAndroid Build Coastguard Worker } 448*795d594fSAndroid Build Coastguard Worker return is_free; 449*795d594fSAndroid Build Coastguard Worker } 450*795d594fSAndroid Build Coastguard Worker 451*795d594fSAndroid Build Coastguard Worker // Given a free region, declare it non-free (allocated). 452*795d594fSAndroid Build Coastguard Worker void Unfree(RegionSpace* region_space, uint32_t alloc_time) 453*795d594fSAndroid Build Coastguard Worker REQUIRES(region_space->region_lock_); 454*795d594fSAndroid Build Coastguard Worker 455*795d594fSAndroid Build Coastguard Worker // Given a free region, declare it non-free (allocated) and large. 456*795d594fSAndroid Build Coastguard Worker EXPORT void UnfreeLarge(RegionSpace* region_space, uint32_t alloc_time) 457*795d594fSAndroid Build Coastguard Worker REQUIRES(region_space->region_lock_); 458*795d594fSAndroid Build Coastguard Worker 459*795d594fSAndroid Build Coastguard Worker // Given a free region, declare it non-free (allocated) and large tail. 460*795d594fSAndroid Build Coastguard Worker EXPORT void UnfreeLargeTail(RegionSpace* region_space, uint32_t alloc_time) 461*795d594fSAndroid Build Coastguard Worker REQUIRES(region_space->region_lock_); 462*795d594fSAndroid Build Coastguard Worker 463*795d594fSAndroid Build Coastguard Worker void MarkAsAllocated(RegionSpace* region_space, uint32_t alloc_time) 464*795d594fSAndroid Build Coastguard Worker REQUIRES(region_space->region_lock_); 465*795d594fSAndroid Build Coastguard Worker SetNewlyAllocated()466*795d594fSAndroid Build Coastguard Worker void SetNewlyAllocated() { 467*795d594fSAndroid Build Coastguard Worker is_newly_allocated_ = true; 468*795d594fSAndroid Build Coastguard Worker } 469*795d594fSAndroid Build Coastguard Worker 470*795d594fSAndroid Build Coastguard Worker // Non-large, non-large-tail allocated. IsAllocated()471*795d594fSAndroid Build Coastguard Worker bool IsAllocated() const { 472*795d594fSAndroid Build Coastguard Worker return state_ == RegionState::kRegionStateAllocated; 473*795d594fSAndroid Build Coastguard Worker } 474*795d594fSAndroid Build Coastguard Worker 475*795d594fSAndroid Build Coastguard Worker // Large allocated. IsLarge()476*795d594fSAndroid Build Coastguard Worker bool IsLarge() const { 477*795d594fSAndroid Build Coastguard Worker bool is_large = (state_ == RegionState::kRegionStateLarge); 478*795d594fSAndroid Build Coastguard Worker if (is_large) { 479*795d594fSAndroid Build Coastguard Worker DCHECK_LT(begin_ + kRegionSize, Top()); 480*795d594fSAndroid Build Coastguard Worker } 481*795d594fSAndroid Build Coastguard Worker return is_large; 482*795d594fSAndroid Build Coastguard Worker } 483*795d594fSAndroid Build Coastguard Worker ZeroLiveBytes()484*795d594fSAndroid Build Coastguard Worker void ZeroLiveBytes() { 485*795d594fSAndroid Build Coastguard Worker live_bytes_ = 0; 486*795d594fSAndroid Build Coastguard Worker } 487*795d594fSAndroid Build Coastguard Worker 488*795d594fSAndroid Build Coastguard Worker // Large-tail allocated. IsLargeTail()489*795d594fSAndroid Build Coastguard Worker bool IsLargeTail() const { 490*795d594fSAndroid Build Coastguard Worker bool is_large_tail = (state_ == RegionState::kRegionStateLargeTail); 491*795d594fSAndroid Build Coastguard Worker if (is_large_tail) { 492*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(begin_, Top()); 493*795d594fSAndroid Build Coastguard Worker } 494*795d594fSAndroid Build Coastguard Worker return is_large_tail; 495*795d594fSAndroid Build Coastguard Worker } 496*795d594fSAndroid Build Coastguard Worker Idx()497*795d594fSAndroid Build Coastguard Worker size_t Idx() const { 498*795d594fSAndroid Build Coastguard Worker return idx_; 499*795d594fSAndroid Build Coastguard Worker } 500*795d594fSAndroid Build Coastguard Worker IsNewlyAllocated()501*795d594fSAndroid Build Coastguard Worker bool IsNewlyAllocated() const { 502*795d594fSAndroid Build Coastguard Worker return is_newly_allocated_; 503*795d594fSAndroid Build Coastguard Worker } 504*795d594fSAndroid Build Coastguard Worker IsTlab()505*795d594fSAndroid Build Coastguard Worker bool IsTlab() const { 506*795d594fSAndroid Build Coastguard Worker return is_a_tlab_; 507*795d594fSAndroid Build Coastguard Worker } 508*795d594fSAndroid Build Coastguard Worker IsInFromSpace()509*795d594fSAndroid Build Coastguard Worker bool IsInFromSpace() const { 510*795d594fSAndroid Build Coastguard Worker return type_ == RegionType::kRegionTypeFromSpace; 511*795d594fSAndroid Build Coastguard Worker } 512*795d594fSAndroid Build Coastguard Worker IsInToSpace()513*795d594fSAndroid Build Coastguard Worker bool IsInToSpace() const { 514*795d594fSAndroid Build Coastguard Worker return type_ == RegionType::kRegionTypeToSpace; 515*795d594fSAndroid Build Coastguard Worker } 516*795d594fSAndroid Build Coastguard Worker IsInUnevacFromSpace()517*795d594fSAndroid Build Coastguard Worker bool IsInUnevacFromSpace() const { 518*795d594fSAndroid Build Coastguard Worker return type_ == RegionType::kRegionTypeUnevacFromSpace; 519*795d594fSAndroid Build Coastguard Worker } 520*795d594fSAndroid Build Coastguard Worker IsInNoSpace()521*795d594fSAndroid Build Coastguard Worker bool IsInNoSpace() const { 522*795d594fSAndroid Build Coastguard Worker return type_ == RegionType::kRegionTypeNone; 523*795d594fSAndroid Build Coastguard Worker } 524*795d594fSAndroid Build Coastguard Worker 525*795d594fSAndroid Build Coastguard Worker // Set this region as evacuated from-space. At the end of the 526*795d594fSAndroid Build Coastguard Worker // collection, RegionSpace::ClearFromSpace will clear and reclaim 527*795d594fSAndroid Build Coastguard Worker // the space used by this region, and tag it as unallocated/free. SetAsFromSpace()528*795d594fSAndroid Build Coastguard Worker void SetAsFromSpace() { 529*795d594fSAndroid Build Coastguard Worker DCHECK(!IsFree() && IsInToSpace()); 530*795d594fSAndroid Build Coastguard Worker type_ = RegionType::kRegionTypeFromSpace; 531*795d594fSAndroid Build Coastguard Worker if (IsNewlyAllocated()) { 532*795d594fSAndroid Build Coastguard Worker // Clear the "newly allocated" status here, as we do not want the 533*795d594fSAndroid Build Coastguard Worker // GC to see it when encountering references in the from-space. 534*795d594fSAndroid Build Coastguard Worker // 535*795d594fSAndroid Build Coastguard Worker // Invariant: There should be no newly-allocated region in the 536*795d594fSAndroid Build Coastguard Worker // from-space (when the from-space exists, which is between the calls 537*795d594fSAndroid Build Coastguard Worker // to RegionSpace::SetFromSpace and RegionSpace::ClearFromSpace). 538*795d594fSAndroid Build Coastguard Worker is_newly_allocated_ = false; 539*795d594fSAndroid Build Coastguard Worker } 540*795d594fSAndroid Build Coastguard Worker // Set live bytes to an invalid value, as we have made an 541*795d594fSAndroid Build Coastguard Worker // evacuation decision (possibly based on the percentage of live 542*795d594fSAndroid Build Coastguard Worker // bytes). 543*795d594fSAndroid Build Coastguard Worker live_bytes_ = static_cast<size_t>(-1); 544*795d594fSAndroid Build Coastguard Worker } 545*795d594fSAndroid Build Coastguard Worker 546*795d594fSAndroid Build Coastguard Worker // Set this region as unevacuated from-space. At the end of the 547*795d594fSAndroid Build Coastguard Worker // collection, RegionSpace::ClearFromSpace will preserve the space 548*795d594fSAndroid Build Coastguard Worker // used by this region, and tag it as to-space (see 549*795d594fSAndroid Build Coastguard Worker // Region::SetUnevacFromSpaceAsToSpace below). 550*795d594fSAndroid Build Coastguard Worker void SetAsUnevacFromSpace(bool clear_live_bytes); 551*795d594fSAndroid Build Coastguard Worker 552*795d594fSAndroid Build Coastguard Worker // Set this region as to-space. Used by RegionSpace::ClearFromSpace. 553*795d594fSAndroid Build Coastguard Worker // This is only valid if it is currently an unevac from-space region. SetUnevacFromSpaceAsToSpace()554*795d594fSAndroid Build Coastguard Worker void SetUnevacFromSpaceAsToSpace() { 555*795d594fSAndroid Build Coastguard Worker DCHECK(!IsFree() && IsInUnevacFromSpace()); 556*795d594fSAndroid Build Coastguard Worker type_ = RegionType::kRegionTypeToSpace; 557*795d594fSAndroid Build Coastguard Worker } 558*795d594fSAndroid Build Coastguard Worker 559*795d594fSAndroid Build Coastguard Worker // Return whether this region should be evacuated. Used by RegionSpace::SetFromSpace. 560*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE bool ShouldBeEvacuated(EvacMode evac_mode); 561*795d594fSAndroid Build Coastguard Worker AddLiveBytes(size_t live_bytes)562*795d594fSAndroid Build Coastguard Worker void AddLiveBytes(size_t live_bytes) { 563*795d594fSAndroid Build Coastguard Worker DCHECK(GetUseGenerationalCC() || IsInUnevacFromSpace()); 564*795d594fSAndroid Build Coastguard Worker DCHECK(!IsLargeTail()); 565*795d594fSAndroid Build Coastguard Worker DCHECK_NE(live_bytes_, static_cast<size_t>(-1)); 566*795d594fSAndroid Build Coastguard Worker // For large allocations, we always consider all bytes in the regions live. 567*795d594fSAndroid Build Coastguard Worker live_bytes_ += IsLarge() ? Top() - begin_ : live_bytes; 568*795d594fSAndroid Build Coastguard Worker DCHECK_LE(live_bytes_, BytesAllocated()); 569*795d594fSAndroid Build Coastguard Worker } 570*795d594fSAndroid Build Coastguard Worker AllAllocatedBytesAreLive()571*795d594fSAndroid Build Coastguard Worker bool AllAllocatedBytesAreLive() const { 572*795d594fSAndroid Build Coastguard Worker return LiveBytes() == static_cast<size_t>(Top() - Begin()); 573*795d594fSAndroid Build Coastguard Worker } 574*795d594fSAndroid Build Coastguard Worker LiveBytes()575*795d594fSAndroid Build Coastguard Worker size_t LiveBytes() const { 576*795d594fSAndroid Build Coastguard Worker return live_bytes_; 577*795d594fSAndroid Build Coastguard Worker } 578*795d594fSAndroid Build Coastguard Worker 579*795d594fSAndroid Build Coastguard Worker // Returns the number of allocated bytes. "Bulk allocated" bytes in active TLABs are excluded. 580*795d594fSAndroid Build Coastguard Worker size_t BytesAllocated() const; 581*795d594fSAndroid Build Coastguard Worker 582*795d594fSAndroid Build Coastguard Worker size_t ObjectsAllocated() const; 583*795d594fSAndroid Build Coastguard Worker Begin()584*795d594fSAndroid Build Coastguard Worker uint8_t* Begin() const { 585*795d594fSAndroid Build Coastguard Worker return begin_; 586*795d594fSAndroid Build Coastguard Worker } 587*795d594fSAndroid Build Coastguard Worker Top()588*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE uint8_t* Top() const { 589*795d594fSAndroid Build Coastguard Worker return top_.load(std::memory_order_relaxed); 590*795d594fSAndroid Build Coastguard Worker } 591*795d594fSAndroid Build Coastguard Worker SetTop(uint8_t * new_top)592*795d594fSAndroid Build Coastguard Worker void SetTop(uint8_t* new_top) { 593*795d594fSAndroid Build Coastguard Worker top_.store(new_top, std::memory_order_relaxed); 594*795d594fSAndroid Build Coastguard Worker } 595*795d594fSAndroid Build Coastguard Worker End()596*795d594fSAndroid Build Coastguard Worker uint8_t* End() const { 597*795d594fSAndroid Build Coastguard Worker return end_; 598*795d594fSAndroid Build Coastguard Worker } 599*795d594fSAndroid Build Coastguard Worker Contains(mirror::Object * ref)600*795d594fSAndroid Build Coastguard Worker bool Contains(mirror::Object* ref) const { 601*795d594fSAndroid Build Coastguard Worker return begin_ <= reinterpret_cast<uint8_t*>(ref) && reinterpret_cast<uint8_t*>(ref) < end_; 602*795d594fSAndroid Build Coastguard Worker } 603*795d594fSAndroid Build Coastguard Worker 604*795d594fSAndroid Build Coastguard Worker void Dump(std::ostream& os) const; 605*795d594fSAndroid Build Coastguard Worker RecordThreadLocalAllocations(size_t num_objects,size_t num_bytes)606*795d594fSAndroid Build Coastguard Worker void RecordThreadLocalAllocations(size_t num_objects, size_t num_bytes) { 607*795d594fSAndroid Build Coastguard Worker DCHECK(IsAllocated()); 608*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(Top(), end_); 609*795d594fSAndroid Build Coastguard Worker objects_allocated_.fetch_add(num_objects, std::memory_order_relaxed); 610*795d594fSAndroid Build Coastguard Worker top_.store(begin_ + num_bytes, std::memory_order_relaxed); 611*795d594fSAndroid Build Coastguard Worker DCHECK_LE(Top(), end_); 612*795d594fSAndroid Build Coastguard Worker } 613*795d594fSAndroid Build Coastguard Worker 614*795d594fSAndroid Build Coastguard Worker uint64_t GetLongestConsecutiveFreeBytes() const; 615*795d594fSAndroid Build Coastguard Worker 616*795d594fSAndroid Build Coastguard Worker private: 617*795d594fSAndroid Build Coastguard Worker static bool GetUseGenerationalCC(); 618*795d594fSAndroid Build Coastguard Worker 619*795d594fSAndroid Build Coastguard Worker size_t idx_; // The region's index in the region space. 620*795d594fSAndroid Build Coastguard Worker // Number of bytes in live objects, or -1 for newly allocated regions. Used to compute 621*795d594fSAndroid Build Coastguard Worker // percent live for region evacuation decisions, and to determine whether an unevacuated 622*795d594fSAndroid Build Coastguard Worker // region is completely empty, and thus can be reclaimed. Reset to zero either at the 623*795d594fSAndroid Build Coastguard Worker // beginning of MarkingPhase(), or during the flip for a nongenerational GC, where we 624*795d594fSAndroid Build Coastguard Worker // don't have a separate mark phase. It is then incremented whenever a mark bit in that 625*795d594fSAndroid Build Coastguard Worker // region is set. 626*795d594fSAndroid Build Coastguard Worker size_t live_bytes_; // The live bytes. Used to compute the live percent. 627*795d594fSAndroid Build Coastguard Worker uint8_t* begin_; // The begin address of the region. 628*795d594fSAndroid Build Coastguard Worker Thread* thread_; // The owning thread if it's a tlab. 629*795d594fSAndroid Build Coastguard Worker // Note that `top_` can be higher than `end_` in the case of a 630*795d594fSAndroid Build Coastguard Worker // large region, where an allocated object spans multiple regions 631*795d594fSAndroid Build Coastguard Worker // (large region + one or more large tail regions). 632*795d594fSAndroid Build Coastguard Worker Atomic<uint8_t*> top_; // The current position of the allocation. 633*795d594fSAndroid Build Coastguard Worker uint8_t* end_; // The end address of the region. 634*795d594fSAndroid Build Coastguard Worker // objects_allocated_ is accessed using memory_order_relaxed. Treat as approximate when there 635*795d594fSAndroid Build Coastguard Worker // are concurrent updates. 636*795d594fSAndroid Build Coastguard Worker Atomic<size_t> objects_allocated_; // The number of objects allocated. 637*795d594fSAndroid Build Coastguard Worker uint32_t alloc_time_; // The allocation time of the region. 638*795d594fSAndroid Build Coastguard Worker // Note that newly allocated and evacuated regions use -1 as 639*795d594fSAndroid Build Coastguard Worker // special value for `live_bytes_`. 640*795d594fSAndroid Build Coastguard Worker bool is_newly_allocated_; // True if it's allocated after the last collection. 641*795d594fSAndroid Build Coastguard Worker bool is_a_tlab_; // True if it's a tlab. 642*795d594fSAndroid Build Coastguard Worker RegionState state_; // The region state (see RegionState). 643*795d594fSAndroid Build Coastguard Worker RegionType type_; // The region type (see RegionType). 644*795d594fSAndroid Build Coastguard Worker 645*795d594fSAndroid Build Coastguard Worker friend class RegionSpace; 646*795d594fSAndroid Build Coastguard Worker }; 647*795d594fSAndroid Build Coastguard Worker 648*795d594fSAndroid Build Coastguard Worker template<bool kToSpaceOnly, typename Visitor> 649*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE void WalkInternal(Visitor&& visitor) NO_THREAD_SAFETY_ANALYSIS; 650*795d594fSAndroid Build Coastguard Worker 651*795d594fSAndroid Build Coastguard Worker // Visitor will be iterating on objects in increasing address order. 652*795d594fSAndroid Build Coastguard Worker template<typename Visitor> 653*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE void WalkNonLargeRegion(Visitor&& visitor, const Region* r) 654*795d594fSAndroid Build Coastguard Worker NO_THREAD_SAFETY_ANALYSIS; 655*795d594fSAndroid Build Coastguard Worker RefToRegion(mirror::Object * ref)656*795d594fSAndroid Build Coastguard Worker Region* RefToRegion(mirror::Object* ref) REQUIRES(!region_lock_) { 657*795d594fSAndroid Build Coastguard Worker MutexLock mu(Thread::Current(), region_lock_); 658*795d594fSAndroid Build Coastguard Worker return RefToRegionLocked(ref); 659*795d594fSAndroid Build Coastguard Worker } 660*795d594fSAndroid Build Coastguard Worker 661*795d594fSAndroid Build Coastguard Worker void TraceHeapSize() REQUIRES(region_lock_); 662*795d594fSAndroid Build Coastguard Worker RefToRegionUnlocked(mirror::Object * ref)663*795d594fSAndroid Build Coastguard Worker Region* RefToRegionUnlocked(mirror::Object* ref) NO_THREAD_SAFETY_ANALYSIS { 664*795d594fSAndroid Build Coastguard Worker // For a performance reason (this is frequently called via 665*795d594fSAndroid Build Coastguard Worker // RegionSpace::IsInFromSpace, etc.) we avoid taking a lock here. 666*795d594fSAndroid Build Coastguard Worker // Note that since we only change a region from to-space to (evac) 667*795d594fSAndroid Build Coastguard Worker // from-space during a pause (in RegionSpace::SetFromSpace) and 668*795d594fSAndroid Build Coastguard Worker // from (evac) from-space to free (after GC is done), as long as 669*795d594fSAndroid Build Coastguard Worker // `ref` is a valid reference into an allocated region, it's safe 670*795d594fSAndroid Build Coastguard Worker // to access the region state without the lock. 671*795d594fSAndroid Build Coastguard Worker return RefToRegionLocked(ref); 672*795d594fSAndroid Build Coastguard Worker } 673*795d594fSAndroid Build Coastguard Worker RefToRegionLocked(mirror::Object * ref)674*795d594fSAndroid Build Coastguard Worker Region* RefToRegionLocked(mirror::Object* ref) REQUIRES(region_lock_) { 675*795d594fSAndroid Build Coastguard Worker DCHECK(HasAddress(ref)); 676*795d594fSAndroid Build Coastguard Worker uintptr_t offset = reinterpret_cast<uintptr_t>(ref) - reinterpret_cast<uintptr_t>(Begin()); 677*795d594fSAndroid Build Coastguard Worker size_t reg_idx = offset / kRegionSize; 678*795d594fSAndroid Build Coastguard Worker DCHECK_LT(reg_idx, num_regions_); 679*795d594fSAndroid Build Coastguard Worker Region* reg = ®ions_[reg_idx]; 680*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(reg->Idx(), reg_idx); 681*795d594fSAndroid Build Coastguard Worker DCHECK(reg->Contains(ref)); 682*795d594fSAndroid Build Coastguard Worker return reg; 683*795d594fSAndroid Build Coastguard Worker } 684*795d594fSAndroid Build Coastguard Worker 685*795d594fSAndroid Build Coastguard Worker // Return the object location following `obj` in the region space 686*795d594fSAndroid Build Coastguard Worker // (i.e., the object location at `obj + obj->SizeOf()`). 687*795d594fSAndroid Build Coastguard Worker // 688*795d594fSAndroid Build Coastguard Worker // Note that unless 689*795d594fSAndroid Build Coastguard Worker // - the region containing `obj` is fully used; and 690*795d594fSAndroid Build Coastguard Worker // - `obj` is not the last object of that region; 691*795d594fSAndroid Build Coastguard Worker // the returned location is not guaranteed to be a valid object. 692*795d594fSAndroid Build Coastguard Worker static mirror::Object* GetNextObject(mirror::Object* obj) 693*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_); 694*795d594fSAndroid Build Coastguard Worker AdjustNonFreeRegionLimit(size_t new_non_free_region_index)695*795d594fSAndroid Build Coastguard Worker void AdjustNonFreeRegionLimit(size_t new_non_free_region_index) REQUIRES(region_lock_) { 696*795d594fSAndroid Build Coastguard Worker DCHECK_LT(new_non_free_region_index, num_regions_); 697*795d594fSAndroid Build Coastguard Worker non_free_region_index_limit_ = std::max(non_free_region_index_limit_, 698*795d594fSAndroid Build Coastguard Worker new_non_free_region_index + 1); 699*795d594fSAndroid Build Coastguard Worker VerifyNonFreeRegionLimit(); 700*795d594fSAndroid Build Coastguard Worker } 701*795d594fSAndroid Build Coastguard Worker SetNonFreeRegionLimit(size_t new_non_free_region_index_limit)702*795d594fSAndroid Build Coastguard Worker void SetNonFreeRegionLimit(size_t new_non_free_region_index_limit) REQUIRES(region_lock_) { 703*795d594fSAndroid Build Coastguard Worker DCHECK_LE(new_non_free_region_index_limit, num_regions_); 704*795d594fSAndroid Build Coastguard Worker non_free_region_index_limit_ = new_non_free_region_index_limit; 705*795d594fSAndroid Build Coastguard Worker VerifyNonFreeRegionLimit(); 706*795d594fSAndroid Build Coastguard Worker } 707*795d594fSAndroid Build Coastguard Worker 708*795d594fSAndroid Build Coastguard Worker // Implementation of this invariant: 709*795d594fSAndroid Build Coastguard Worker // for all `i >= non_free_region_index_limit_`, `regions_[i].IsFree()` is true. VerifyNonFreeRegionLimit()710*795d594fSAndroid Build Coastguard Worker void VerifyNonFreeRegionLimit() REQUIRES(region_lock_) { 711*795d594fSAndroid Build Coastguard Worker if (kIsDebugBuild && non_free_region_index_limit_ < num_regions_) { 712*795d594fSAndroid Build Coastguard Worker for (size_t i = non_free_region_index_limit_; i < num_regions_; ++i) { 713*795d594fSAndroid Build Coastguard Worker CHECK(regions_[i].IsFree()); 714*795d594fSAndroid Build Coastguard Worker } 715*795d594fSAndroid Build Coastguard Worker } 716*795d594fSAndroid Build Coastguard Worker } 717*795d594fSAndroid Build Coastguard Worker 718*795d594fSAndroid Build Coastguard Worker EXPORT Region* AllocateRegion(bool for_evac) REQUIRES(region_lock_); 719*795d594fSAndroid Build Coastguard Worker void RevokeThreadLocalBuffersLocked(Thread* thread, bool reuse) REQUIRES(region_lock_); 720*795d594fSAndroid Build Coastguard Worker 721*795d594fSAndroid Build Coastguard Worker // Scan region range [`begin`, `end`) in increasing order to try to 722*795d594fSAndroid Build Coastguard Worker // allocate a large region having a size of `num_regs_in_large_region` 723*795d594fSAndroid Build Coastguard Worker // regions. If there is no space in the region space to allocate this 724*795d594fSAndroid Build Coastguard Worker // large region, return null. 725*795d594fSAndroid Build Coastguard Worker // 726*795d594fSAndroid Build Coastguard Worker // If argument `next_region` is not null, use `*next_region` to 727*795d594fSAndroid Build Coastguard Worker // return the index to the region next to the allocated large region 728*795d594fSAndroid Build Coastguard Worker // returned by this method. 729*795d594fSAndroid Build Coastguard Worker template<bool kForEvac> 730*795d594fSAndroid Build Coastguard Worker mirror::Object* AllocLargeInRange(size_t begin, 731*795d594fSAndroid Build Coastguard Worker size_t end, 732*795d594fSAndroid Build Coastguard Worker size_t num_regs_in_large_region, 733*795d594fSAndroid Build Coastguard Worker /* out */ size_t* bytes_allocated, 734*795d594fSAndroid Build Coastguard Worker /* out */ size_t* usable_size, 735*795d594fSAndroid Build Coastguard Worker /* out */ size_t* bytes_tl_bulk_allocated, 736*795d594fSAndroid Build Coastguard Worker /* out */ size_t* next_region = nullptr) REQUIRES(region_lock_); 737*795d594fSAndroid Build Coastguard Worker 738*795d594fSAndroid Build Coastguard Worker // Check that the value of `r->LiveBytes()` matches the number of 739*795d594fSAndroid Build Coastguard Worker // (allocated) bytes used by live objects according to the live bits 740*795d594fSAndroid Build Coastguard Worker // in the region space bitmap range corresponding to region `r`. 741*795d594fSAndroid Build Coastguard Worker void CheckLiveBytesAgainstRegionBitmap(Region* r); 742*795d594fSAndroid Build Coastguard Worker 743*795d594fSAndroid Build Coastguard Worker // Poison memory areas used by dead objects within unevacuated 744*795d594fSAndroid Build Coastguard Worker // region `r`. This is meant to detect dangling references to dead 745*795d594fSAndroid Build Coastguard Worker // objects earlier in debug mode. 746*795d594fSAndroid Build Coastguard Worker void PoisonDeadObjectsInUnevacuatedRegion(Region* r); 747*795d594fSAndroid Build Coastguard Worker 748*795d594fSAndroid Build Coastguard Worker Mutex region_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER; 749*795d594fSAndroid Build Coastguard Worker 750*795d594fSAndroid Build Coastguard Worker // Cached version of Heap::use_generational_cc_. 751*795d594fSAndroid Build Coastguard Worker const bool use_generational_cc_; 752*795d594fSAndroid Build Coastguard Worker uint32_t time_; // The time as the number of collections since the startup. 753*795d594fSAndroid Build Coastguard Worker size_t num_regions_; // The number of regions in this space. 754*795d594fSAndroid Build Coastguard Worker uint64_t madvise_time_; // The amount of time spent in madvise for purging pages. 755*795d594fSAndroid Build Coastguard Worker // The number of non-free regions in this space. 756*795d594fSAndroid Build Coastguard Worker size_t num_non_free_regions_ GUARDED_BY(region_lock_); 757*795d594fSAndroid Build Coastguard Worker 758*795d594fSAndroid Build Coastguard Worker // The number of evac regions allocated during collection. 0 when GC not running. 759*795d594fSAndroid Build Coastguard Worker size_t num_evac_regions_ GUARDED_BY(region_lock_); 760*795d594fSAndroid Build Coastguard Worker 761*795d594fSAndroid Build Coastguard Worker // Maintain the maximum of number of non-free regions collected just before 762*795d594fSAndroid Build Coastguard Worker // reclaim in each GC cycle. At this moment in cycle, highest number of 763*795d594fSAndroid Build Coastguard Worker // regions are in non-free. 764*795d594fSAndroid Build Coastguard Worker size_t max_peak_num_non_free_regions_; 765*795d594fSAndroid Build Coastguard Worker 766*795d594fSAndroid Build Coastguard Worker // The pointer to the region array. 767*795d594fSAndroid Build Coastguard Worker std::unique_ptr<Region[]> regions_ GUARDED_BY(region_lock_); 768*795d594fSAndroid Build Coastguard Worker 769*795d594fSAndroid Build Coastguard Worker // To hold partially used TLABs which can be reassigned to threads later for 770*795d594fSAndroid Build Coastguard Worker // utilizing the un-used portion. 771*795d594fSAndroid Build Coastguard Worker std::multimap<size_t, Region*, std::greater<size_t>> partial_tlabs_ GUARDED_BY(region_lock_); 772*795d594fSAndroid Build Coastguard Worker // The upper-bound index of the non-free regions. Used to avoid scanning all regions in 773*795d594fSAndroid Build Coastguard Worker // RegionSpace::SetFromSpace and RegionSpace::ClearFromSpace. 774*795d594fSAndroid Build Coastguard Worker // 775*795d594fSAndroid Build Coastguard Worker // Invariant (verified by RegionSpace::VerifyNonFreeRegionLimit): 776*795d594fSAndroid Build Coastguard Worker // for all `i >= non_free_region_index_limit_`, `regions_[i].IsFree()` is true. 777*795d594fSAndroid Build Coastguard Worker size_t non_free_region_index_limit_ GUARDED_BY(region_lock_); 778*795d594fSAndroid Build Coastguard Worker 779*795d594fSAndroid Build Coastguard Worker Region* current_region_; // The region currently used for allocation. 780*795d594fSAndroid Build Coastguard Worker Region* evac_region_; // The region currently used for evacuation. 781*795d594fSAndroid Build Coastguard Worker Region full_region_; // The fake/sentinel region that looks full. 782*795d594fSAndroid Build Coastguard Worker 783*795d594fSAndroid Build Coastguard Worker // Index into the region array pointing to the starting region when 784*795d594fSAndroid Build Coastguard Worker // trying to allocate a new region. Only used when 785*795d594fSAndroid Build Coastguard Worker // `kCyclicRegionAllocation` is true. 786*795d594fSAndroid Build Coastguard Worker size_t cyclic_alloc_region_index_ GUARDED_BY(region_lock_); 787*795d594fSAndroid Build Coastguard Worker 788*795d594fSAndroid Build Coastguard Worker // Mark bitmap used by the GC. 789*795d594fSAndroid Build Coastguard Worker accounting::ContinuousSpaceBitmap mark_bitmap_; 790*795d594fSAndroid Build Coastguard Worker 791*795d594fSAndroid Build Coastguard Worker DISALLOW_COPY_AND_ASSIGN(RegionSpace); 792*795d594fSAndroid Build Coastguard Worker }; 793*795d594fSAndroid Build Coastguard Worker 794*795d594fSAndroid Build Coastguard Worker std::ostream& operator<<(std::ostream& os, RegionSpace::RegionState value); 795*795d594fSAndroid Build Coastguard Worker std::ostream& operator<<(std::ostream& os, RegionSpace::RegionType value); 796*795d594fSAndroid Build Coastguard Worker 797*795d594fSAndroid Build Coastguard Worker } // namespace space 798*795d594fSAndroid Build Coastguard Worker } // namespace gc 799*795d594fSAndroid Build Coastguard Worker } // namespace art 800*795d594fSAndroid Build Coastguard Worker 801*795d594fSAndroid Build Coastguard Worker #endif // ART_RUNTIME_GC_SPACE_REGION_SPACE_H_ 802