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