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