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