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