xref: /aosp_15_r20/art/runtime/gc/space/region_space.h (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
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 = &regions_[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 = &regions_[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 = &regions_[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 = &regions_[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