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 GetMadviseTime()383 uint64_t GetMadviseTime() const { 384 return madvise_time_; 385 } 386 387 private: 388 RegionSpace(const std::string& name, MemMap&& mem_map, bool use_generational_cc); 389 390 class Region { 391 public: Region()392 Region() 393 : idx_(static_cast<size_t>(-1)), 394 live_bytes_(static_cast<size_t>(-1)), 395 begin_(nullptr), 396 thread_(nullptr), 397 top_(nullptr), 398 end_(nullptr), 399 objects_allocated_(0), 400 alloc_time_(0), 401 is_newly_allocated_(false), 402 is_a_tlab_(false), 403 state_(RegionState::kRegionStateAllocated), 404 type_(RegionType::kRegionTypeToSpace) {} 405 Init(size_t idx,uint8_t * begin,uint8_t * end)406 void Init(size_t idx, uint8_t* begin, uint8_t* end) { 407 idx_ = idx; 408 begin_ = begin; 409 top_.store(begin, std::memory_order_relaxed); 410 end_ = end; 411 state_ = RegionState::kRegionStateFree; 412 type_ = RegionType::kRegionTypeNone; 413 objects_allocated_.store(0, std::memory_order_relaxed); 414 alloc_time_ = 0; 415 live_bytes_ = static_cast<size_t>(-1); 416 is_newly_allocated_ = false; 417 is_a_tlab_ = false; 418 thread_ = nullptr; 419 DCHECK_LT(begin, end); 420 DCHECK_EQ(static_cast<size_t>(end - begin), kRegionSize); 421 } 422 State()423 RegionState State() const { 424 return state_; 425 } 426 Type()427 RegionType Type() const { 428 return type_; 429 } 430 431 void Clear(bool zero_and_release_pages); 432 433 ALWAYS_INLINE mirror::Object* Alloc(size_t num_bytes, 434 /* out */ size_t* bytes_allocated, 435 /* out */ size_t* usable_size, 436 /* out */ size_t* bytes_tl_bulk_allocated); 437 IsFree()438 bool IsFree() const { 439 bool is_free = (state_ == RegionState::kRegionStateFree); 440 if (is_free) { 441 DCHECK(IsInNoSpace()); 442 DCHECK_EQ(begin_, Top()); 443 DCHECK_EQ(objects_allocated_.load(std::memory_order_relaxed), 0U); 444 } 445 return is_free; 446 } 447 448 // Given a free region, declare it non-free (allocated). 449 void Unfree(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. 453 void UnfreeLarge(RegionSpace* region_space, uint32_t alloc_time) 454 REQUIRES(region_space->region_lock_); 455 456 // Given a free region, declare it non-free (allocated) and large tail. 457 void UnfreeLargeTail(RegionSpace* region_space, uint32_t alloc_time) 458 REQUIRES(region_space->region_lock_); 459 460 void MarkAsAllocated(RegionSpace* region_space, uint32_t alloc_time) 461 REQUIRES(region_space->region_lock_); 462 SetNewlyAllocated()463 void SetNewlyAllocated() { 464 is_newly_allocated_ = true; 465 } 466 467 // Non-large, non-large-tail allocated. IsAllocated()468 bool IsAllocated() const { 469 return state_ == RegionState::kRegionStateAllocated; 470 } 471 472 // Large allocated. IsLarge()473 bool IsLarge() const { 474 bool is_large = (state_ == RegionState::kRegionStateLarge); 475 if (is_large) { 476 DCHECK_LT(begin_ + kRegionSize, Top()); 477 } 478 return is_large; 479 } 480 ZeroLiveBytes()481 void ZeroLiveBytes() { 482 live_bytes_ = 0; 483 } 484 485 // Large-tail allocated. IsLargeTail()486 bool IsLargeTail() const { 487 bool is_large_tail = (state_ == RegionState::kRegionStateLargeTail); 488 if (is_large_tail) { 489 DCHECK_EQ(begin_, Top()); 490 } 491 return is_large_tail; 492 } 493 Idx()494 size_t Idx() const { 495 return idx_; 496 } 497 IsNewlyAllocated()498 bool IsNewlyAllocated() const { 499 return is_newly_allocated_; 500 } 501 IsTlab()502 bool IsTlab() const { 503 return is_a_tlab_; 504 } 505 IsInFromSpace()506 bool IsInFromSpace() const { 507 return type_ == RegionType::kRegionTypeFromSpace; 508 } 509 IsInToSpace()510 bool IsInToSpace() const { 511 return type_ == RegionType::kRegionTypeToSpace; 512 } 513 IsInUnevacFromSpace()514 bool IsInUnevacFromSpace() const { 515 return type_ == RegionType::kRegionTypeUnevacFromSpace; 516 } 517 IsInNoSpace()518 bool IsInNoSpace() const { 519 return type_ == RegionType::kRegionTypeNone; 520 } 521 522 // Set this region as evacuated from-space. At the end of the 523 // collection, RegionSpace::ClearFromSpace will clear and reclaim 524 // the space used by this region, and tag it as unallocated/free. SetAsFromSpace()525 void SetAsFromSpace() { 526 DCHECK(!IsFree() && IsInToSpace()); 527 type_ = RegionType::kRegionTypeFromSpace; 528 if (IsNewlyAllocated()) { 529 // Clear the "newly allocated" status here, as we do not want the 530 // GC to see it when encountering references in the from-space. 531 // 532 // Invariant: There should be no newly-allocated region in the 533 // from-space (when the from-space exists, which is between the calls 534 // to RegionSpace::SetFromSpace and RegionSpace::ClearFromSpace). 535 is_newly_allocated_ = false; 536 } 537 // Set live bytes to an invalid value, as we have made an 538 // evacuation decision (possibly based on the percentage of live 539 // bytes). 540 live_bytes_ = static_cast<size_t>(-1); 541 } 542 543 // Set this region as unevacuated from-space. At the end of the 544 // collection, RegionSpace::ClearFromSpace will preserve the space 545 // used by this region, and tag it as to-space (see 546 // Region::SetUnevacFromSpaceAsToSpace below). 547 void SetAsUnevacFromSpace(bool clear_live_bytes); 548 549 // Set this region as to-space. Used by RegionSpace::ClearFromSpace. 550 // This is only valid if it is currently an unevac from-space region. SetUnevacFromSpaceAsToSpace()551 void SetUnevacFromSpaceAsToSpace() { 552 DCHECK(!IsFree() && IsInUnevacFromSpace()); 553 type_ = RegionType::kRegionTypeToSpace; 554 } 555 556 // Return whether this region should be evacuated. Used by RegionSpace::SetFromSpace. 557 ALWAYS_INLINE bool ShouldBeEvacuated(EvacMode evac_mode); 558 AddLiveBytes(size_t live_bytes)559 void AddLiveBytes(size_t live_bytes) { 560 DCHECK(GetUseGenerationalCC() || IsInUnevacFromSpace()); 561 DCHECK(!IsLargeTail()); 562 DCHECK_NE(live_bytes_, static_cast<size_t>(-1)); 563 // For large allocations, we always consider all bytes in the regions live. 564 live_bytes_ += IsLarge() ? Top() - begin_ : live_bytes; 565 DCHECK_LE(live_bytes_, BytesAllocated()); 566 } 567 AllAllocatedBytesAreLive()568 bool AllAllocatedBytesAreLive() const { 569 return LiveBytes() == static_cast<size_t>(Top() - Begin()); 570 } 571 LiveBytes()572 size_t LiveBytes() const { 573 return live_bytes_; 574 } 575 576 // Returns the number of allocated bytes. "Bulk allocated" bytes in active TLABs are excluded. 577 size_t BytesAllocated() const; 578 579 size_t ObjectsAllocated() const; 580 Begin()581 uint8_t* Begin() const { 582 return begin_; 583 } 584 Top()585 ALWAYS_INLINE uint8_t* Top() const { 586 return top_.load(std::memory_order_relaxed); 587 } 588 SetTop(uint8_t * new_top)589 void SetTop(uint8_t* new_top) { 590 top_.store(new_top, std::memory_order_relaxed); 591 } 592 End()593 uint8_t* End() const { 594 return end_; 595 } 596 Contains(mirror::Object * ref)597 bool Contains(mirror::Object* ref) const { 598 return begin_ <= reinterpret_cast<uint8_t*>(ref) && reinterpret_cast<uint8_t*>(ref) < end_; 599 } 600 601 void Dump(std::ostream& os) const; 602 RecordThreadLocalAllocations(size_t num_objects,size_t num_bytes)603 void RecordThreadLocalAllocations(size_t num_objects, size_t num_bytes) { 604 DCHECK(IsAllocated()); 605 DCHECK_EQ(Top(), end_); 606 objects_allocated_.fetch_add(num_objects, std::memory_order_relaxed); 607 top_.store(begin_ + num_bytes, std::memory_order_relaxed); 608 DCHECK_LE(Top(), end_); 609 } 610 611 uint64_t GetLongestConsecutiveFreeBytes() const; 612 613 private: 614 static bool GetUseGenerationalCC(); 615 616 size_t idx_; // The region's index in the region space. 617 size_t live_bytes_; // The live bytes. Used to compute the live percent. 618 uint8_t* begin_; // The begin address of the region. 619 Thread* thread_; // The owning thread if it's a tlab. 620 // Note that `top_` can be higher than `end_` in the case of a 621 // large region, where an allocated object spans multiple regions 622 // (large region + one or more large tail regions). 623 Atomic<uint8_t*> top_; // The current position of the allocation. 624 uint8_t* end_; // The end address of the region. 625 // objects_allocated_ is accessed using memory_order_relaxed. Treat as approximate when there 626 // are concurrent updates. 627 Atomic<size_t> objects_allocated_; // The number of objects allocated. 628 uint32_t alloc_time_; // The allocation time of the region. 629 // Note that newly allocated and evacuated regions use -1 as 630 // special value for `live_bytes_`. 631 bool is_newly_allocated_; // True if it's allocated after the last collection. 632 bool is_a_tlab_; // True if it's a tlab. 633 RegionState state_; // The region state (see RegionState). 634 RegionType type_; // The region type (see RegionType). 635 636 friend class RegionSpace; 637 }; 638 639 template<bool kToSpaceOnly, typename Visitor> 640 ALWAYS_INLINE void WalkInternal(Visitor&& visitor) NO_THREAD_SAFETY_ANALYSIS; 641 642 // Visitor will be iterating on objects in increasing address order. 643 template<typename Visitor> 644 ALWAYS_INLINE void WalkNonLargeRegion(Visitor&& visitor, const Region* r) 645 NO_THREAD_SAFETY_ANALYSIS; 646 RefToRegion(mirror::Object * ref)647 Region* RefToRegion(mirror::Object* ref) REQUIRES(!region_lock_) { 648 MutexLock mu(Thread::Current(), region_lock_); 649 return RefToRegionLocked(ref); 650 } 651 652 void TraceHeapSize() REQUIRES(region_lock_); 653 RefToRegionUnlocked(mirror::Object * ref)654 Region* RefToRegionUnlocked(mirror::Object* ref) NO_THREAD_SAFETY_ANALYSIS { 655 // For a performance reason (this is frequently called via 656 // RegionSpace::IsInFromSpace, etc.) we avoid taking a lock here. 657 // Note that since we only change a region from to-space to (evac) 658 // from-space during a pause (in RegionSpace::SetFromSpace) and 659 // from (evac) from-space to free (after GC is done), as long as 660 // `ref` is a valid reference into an allocated region, it's safe 661 // to access the region state without the lock. 662 return RefToRegionLocked(ref); 663 } 664 RefToRegionLocked(mirror::Object * ref)665 Region* RefToRegionLocked(mirror::Object* ref) REQUIRES(region_lock_) { 666 DCHECK(HasAddress(ref)); 667 uintptr_t offset = reinterpret_cast<uintptr_t>(ref) - reinterpret_cast<uintptr_t>(Begin()); 668 size_t reg_idx = offset / kRegionSize; 669 DCHECK_LT(reg_idx, num_regions_); 670 Region* reg = ®ions_[reg_idx]; 671 DCHECK_EQ(reg->Idx(), reg_idx); 672 DCHECK(reg->Contains(ref)); 673 return reg; 674 } 675 676 // Return the object location following `obj` in the region space 677 // (i.e., the object location at `obj + obj->SizeOf()`). 678 // 679 // Note that unless 680 // - the region containing `obj` is fully used; and 681 // - `obj` is not the last object of that region; 682 // the returned location is not guaranteed to be a valid object. 683 static mirror::Object* GetNextObject(mirror::Object* obj) 684 REQUIRES_SHARED(Locks::mutator_lock_); 685 AdjustNonFreeRegionLimit(size_t new_non_free_region_index)686 void AdjustNonFreeRegionLimit(size_t new_non_free_region_index) REQUIRES(region_lock_) { 687 DCHECK_LT(new_non_free_region_index, num_regions_); 688 non_free_region_index_limit_ = std::max(non_free_region_index_limit_, 689 new_non_free_region_index + 1); 690 VerifyNonFreeRegionLimit(); 691 } 692 SetNonFreeRegionLimit(size_t new_non_free_region_index_limit)693 void SetNonFreeRegionLimit(size_t new_non_free_region_index_limit) REQUIRES(region_lock_) { 694 DCHECK_LE(new_non_free_region_index_limit, num_regions_); 695 non_free_region_index_limit_ = new_non_free_region_index_limit; 696 VerifyNonFreeRegionLimit(); 697 } 698 699 // Implementation of this invariant: 700 // for all `i >= non_free_region_index_limit_`, `regions_[i].IsFree()` is true. VerifyNonFreeRegionLimit()701 void VerifyNonFreeRegionLimit() REQUIRES(region_lock_) { 702 if (kIsDebugBuild && non_free_region_index_limit_ < num_regions_) { 703 for (size_t i = non_free_region_index_limit_; i < num_regions_; ++i) { 704 CHECK(regions_[i].IsFree()); 705 } 706 } 707 } 708 709 Region* AllocateRegion(bool for_evac) REQUIRES(region_lock_); 710 void RevokeThreadLocalBuffersLocked(Thread* thread, bool reuse) REQUIRES(region_lock_); 711 712 // Scan region range [`begin`, `end`) in increasing order to try to 713 // allocate a large region having a size of `num_regs_in_large_region` 714 // regions. If there is no space in the region space to allocate this 715 // large region, return null. 716 // 717 // If argument `next_region` is not null, use `*next_region` to 718 // return the index to the region next to the allocated large region 719 // returned by this method. 720 template<bool kForEvac> 721 mirror::Object* AllocLargeInRange(size_t begin, 722 size_t end, 723 size_t num_regs_in_large_region, 724 /* out */ size_t* bytes_allocated, 725 /* out */ size_t* usable_size, 726 /* out */ size_t* bytes_tl_bulk_allocated, 727 /* out */ size_t* next_region = nullptr) REQUIRES(region_lock_); 728 729 // Check that the value of `r->LiveBytes()` matches the number of 730 // (allocated) bytes used by live objects according to the live bits 731 // in the region space bitmap range corresponding to region `r`. 732 void CheckLiveBytesAgainstRegionBitmap(Region* r); 733 734 // Poison memory areas used by dead objects within unevacuated 735 // region `r`. This is meant to detect dangling references to dead 736 // objects earlier in debug mode. 737 void PoisonDeadObjectsInUnevacuatedRegion(Region* r); 738 739 Mutex region_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER; 740 741 // Cached version of Heap::use_generational_cc_. 742 const bool use_generational_cc_; 743 uint32_t time_; // The time as the number of collections since the startup. 744 size_t num_regions_; // The number of regions in this space. 745 uint64_t madvise_time_; // The amount of time spent in madvise for purging pages. 746 // The number of non-free regions in this space. 747 size_t num_non_free_regions_ GUARDED_BY(region_lock_); 748 749 // The number of evac regions allocated during collection. 0 when GC not running. 750 size_t num_evac_regions_ GUARDED_BY(region_lock_); 751 752 // Maintain the maximum of number of non-free regions collected just before 753 // reclaim in each GC cycle. At this moment in cycle, highest number of 754 // regions are in non-free. 755 size_t max_peak_num_non_free_regions_; 756 757 // The pointer to the region array. 758 std::unique_ptr<Region[]> regions_ GUARDED_BY(region_lock_); 759 760 // To hold partially used TLABs which can be reassigned to threads later for 761 // utilizing the un-used portion. 762 std::multimap<size_t, Region*, std::greater<size_t>> partial_tlabs_ GUARDED_BY(region_lock_); 763 // The upper-bound index of the non-free regions. Used to avoid scanning all regions in 764 // RegionSpace::SetFromSpace and RegionSpace::ClearFromSpace. 765 // 766 // Invariant (verified by RegionSpace::VerifyNonFreeRegionLimit): 767 // for all `i >= non_free_region_index_limit_`, `regions_[i].IsFree()` is true. 768 size_t non_free_region_index_limit_ GUARDED_BY(region_lock_); 769 770 Region* current_region_; // The region currently used for allocation. 771 Region* evac_region_; // The region currently used for evacuation. 772 Region full_region_; // The fake/sentinel region that looks full. 773 774 // Index into the region array pointing to the starting region when 775 // trying to allocate a new region. Only used when 776 // `kCyclicRegionAllocation` is true. 777 size_t cyclic_alloc_region_index_ GUARDED_BY(region_lock_); 778 779 // Mark bitmap used by the GC. 780 accounting::ContinuousSpaceBitmap mark_bitmap_; 781 782 DISALLOW_COPY_AND_ASSIGN(RegionSpace); 783 }; 784 785 std::ostream& operator<<(std::ostream& os, RegionSpace::RegionState value); 786 std::ostream& operator<<(std::ostream& os, RegionSpace::RegionType value); 787 788 } // namespace space 789 } // namespace gc 790 } // namespace art 791 792 #endif // ART_RUNTIME_GC_SPACE_REGION_SPACE_H_ 793