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 = ®ions_[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 = ®ions_[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 = ®ions_[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 = ®ions_[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