1 /* 2 * Copyright (C) 2011 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 #include "space.h" 18 19 #include <android-base/logging.h> 20 21 #include "base/macros.h" 22 #include "gc/accounting/heap_bitmap.h" 23 #include "gc/accounting/space_bitmap-inl.h" 24 #include "gc/heap.h" 25 #include "runtime.h" 26 #include "thread-current-inl.h" 27 28 namespace art { 29 namespace gc { 30 namespace space { 31 32 Space::Space(const std::string& name, GcRetentionPolicy gc_retention_policy) 33 : name_(name), gc_retention_policy_(gc_retention_policy) { } 34 35 void Space::Dump(std::ostream& os) const { 36 os << GetName() << ":" << GetGcRetentionPolicy(); 37 } 38 39 std::ostream& operator<<(std::ostream& os, const Space& space) { 40 space.Dump(os); 41 return os; 42 } 43 44 DlMallocSpace* Space::AsDlMallocSpace() { 45 UNIMPLEMENTED(FATAL) << "Unreachable"; 46 UNREACHABLE(); 47 } 48 49 RosAllocSpace* Space::AsRosAllocSpace() { 50 UNIMPLEMENTED(FATAL) << "Unreachable"; 51 UNREACHABLE(); 52 } 53 54 ZygoteSpace* Space::AsZygoteSpace() { 55 UNIMPLEMENTED(FATAL) << "Unreachable"; 56 UNREACHABLE(); 57 } 58 59 BumpPointerSpace* Space::AsBumpPointerSpace() { 60 UNIMPLEMENTED(FATAL) << "Unreachable"; 61 UNREACHABLE(); 62 } 63 64 RegionSpace* Space::AsRegionSpace() { 65 LOG(FATAL) << "Unreachable"; 66 UNREACHABLE(); 67 } 68 69 AllocSpace* Space::AsAllocSpace() { 70 UNIMPLEMENTED(FATAL) << "Unreachable"; 71 UNREACHABLE(); 72 } 73 74 ContinuousMemMapAllocSpace* Space::AsContinuousMemMapAllocSpace() { 75 UNIMPLEMENTED(FATAL) << "Unreachable"; 76 UNREACHABLE(); 77 } 78 79 DiscontinuousSpace::DiscontinuousSpace(const std::string& name, 80 GcRetentionPolicy gc_retention_policy) : 81 Space(name, gc_retention_policy) { 82 // TODO: Fix this if we ever support objects not in the low 32 bit. 83 const size_t capacity = static_cast<size_t>(std::numeric_limits<uint32_t>::max()); 84 live_bitmap_.reset(accounting::LargeObjectBitmap::Create("large live objects", nullptr, 85 capacity)); 86 CHECK(live_bitmap_.get() != nullptr); 87 mark_bitmap_.reset(accounting::LargeObjectBitmap::Create("large marked objects", nullptr, 88 capacity)); 89 CHECK(mark_bitmap_.get() != nullptr); 90 } 91 92 collector::ObjectBytePair ContinuousMemMapAllocSpace::Sweep(bool swap_bitmaps) { 93 accounting::ContinuousSpaceBitmap* live_bitmap = GetLiveBitmap(); 94 accounting::ContinuousSpaceBitmap* mark_bitmap = GetMarkBitmap(); 95 // If the bitmaps are bound then sweeping this space clearly won't do anything. 96 if (live_bitmap == mark_bitmap) { 97 return collector::ObjectBytePair(0, 0); 98 } 99 SweepCallbackContext scc(swap_bitmaps, this); 100 if (swap_bitmaps) { 101 std::swap(live_bitmap, mark_bitmap); 102 } 103 // Bitmaps are pre-swapped for optimization which enables sweeping with the heap unlocked. 104 accounting::ContinuousSpaceBitmap::SweepWalk( 105 *live_bitmap, *mark_bitmap, reinterpret_cast<uintptr_t>(Begin()), 106 reinterpret_cast<uintptr_t>(End()), GetSweepCallback(), reinterpret_cast<void*>(&scc)); 107 return scc.freed; 108 } 109 110 void ContinuousMemMapAllocSpace::BindLiveToMarkBitmap() { 111 CHECK(!HasBoundBitmaps()); 112 accounting::ContinuousSpaceBitmap* live_bitmap = GetLiveBitmap(); 113 if (live_bitmap != mark_bitmap_.get()) { 114 accounting::ContinuousSpaceBitmap* mark_bitmap = mark_bitmap_.release(); 115 Runtime::Current()->GetHeap()->GetMarkBitmap()->ReplaceBitmap(mark_bitmap, live_bitmap); 116 temp_bitmap_.reset(mark_bitmap); 117 mark_bitmap_.reset(live_bitmap); 118 } 119 } 120 121 bool ContinuousMemMapAllocSpace::HasBoundBitmaps() const { 122 return temp_bitmap_.get() != nullptr; 123 } 124 125 void ContinuousMemMapAllocSpace::UnBindBitmaps() { 126 CHECK(HasBoundBitmaps()); 127 // At this point, `temp_bitmap_` holds our old mark bitmap. 128 accounting::ContinuousSpaceBitmap* new_bitmap = temp_bitmap_.release(); 129 Runtime::Current()->GetHeap()->GetMarkBitmap()->ReplaceBitmap(mark_bitmap_.get(), new_bitmap); 130 CHECK_EQ(mark_bitmap_.release(), live_bitmap_.get()); 131 mark_bitmap_.reset(new_bitmap); 132 DCHECK(temp_bitmap_.get() == nullptr); 133 } 134 135 void ContinuousMemMapAllocSpace::SwapBitmaps() { 136 live_bitmap_.swap(mark_bitmap_); 137 // Swap names to get more descriptive diagnostics. 138 std::string temp_name(live_bitmap_->GetName()); 139 live_bitmap_->SetName(mark_bitmap_->GetName()); 140 mark_bitmap_->SetName(temp_name); 141 } 142 143 AllocSpace::SweepCallbackContext::SweepCallbackContext(bool swap_bitmaps_in, space::Space* space_in) 144 : swap_bitmaps(swap_bitmaps_in), space(space_in), self(Thread::Current()) { 145 } 146 147 } // namespace space 148 } // namespace gc 149 } // namespace art 150