garbage_collector.cc revision 1f3b5358b28a83f0929bdd8ce738f06908677fb7
1/* 2 * Copyright (C) 2012 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#define ATRACE_TAG ATRACE_TAG_DALVIK 18 19#include <stdio.h> 20#include <cutils/trace.h> 21 22#include "garbage_collector.h" 23 24#include "base/histogram-inl.h" 25#include "base/logging.h" 26#include "base/mutex-inl.h" 27#include "gc/accounting/heap_bitmap.h" 28#include "gc/space/large_object_space.h" 29#include "gc/space/space-inl.h" 30#include "thread-inl.h" 31#include "thread_list.h" 32 33namespace art { 34namespace gc { 35namespace collector { 36 37GarbageCollector::GarbageCollector(Heap* heap, const std::string& name) 38 : heap_(heap), 39 name_(name), 40 gc_cause_(kGcCauseForAlloc), 41 clear_soft_references_(false), 42 verbose_(VLOG_IS_ON(heap)), 43 duration_ns_(0), 44 timings_(name_.c_str(), true, verbose_), 45 pause_histogram_((name_ + " paused").c_str(), kPauseBucketSize, kPauseBucketCount), 46 cumulative_timings_(name) { 47 ResetCumulativeStatistics(); 48} 49 50bool GarbageCollector::HandleDirtyObjectsPhase() { 51 DCHECK(IsConcurrent()); 52 return true; 53} 54 55void GarbageCollector::RegisterPause(uint64_t nano_length) { 56 pause_times_.push_back(nano_length); 57} 58 59void GarbageCollector::ResetCumulativeStatistics() { 60 cumulative_timings_.Reset(); 61 pause_histogram_.Reset(); 62 total_time_ns_ = 0; 63 total_freed_objects_ = 0; 64 total_freed_bytes_ = 0; 65} 66 67void GarbageCollector::Run(GcCause gc_cause, bool clear_soft_references) { 68 ThreadList* thread_list = Runtime::Current()->GetThreadList(); 69 Thread* self = Thread::Current(); 70 uint64_t start_time = NanoTime(); 71 pause_times_.clear(); 72 duration_ns_ = 0; 73 clear_soft_references_ = clear_soft_references; 74 gc_cause_ = gc_cause; 75 76 // Reset stats. 77 freed_bytes_ = 0; 78 freed_large_object_bytes_ = 0; 79 freed_objects_ = 0; 80 freed_large_objects_ = 0; 81 82 InitializePhase(); 83 84 if (!IsConcurrent()) { 85 // Pause is the entire length of the GC. 86 uint64_t pause_start = NanoTime(); 87 ATRACE_BEGIN("Application threads suspended"); 88 // Mutator lock may be already exclusively held when we do garbage collections for changing the 89 // current collector / allocator during process state updates. 90 if (Locks::mutator_lock_->IsExclusiveHeld(self)) { 91 GetHeap()->RevokeAllThreadLocalBuffers(); 92 MarkingPhase(); 93 ReclaimPhase(); 94 } else { 95 thread_list->SuspendAll(); 96 GetHeap()->RevokeAllThreadLocalBuffers(); 97 MarkingPhase(); 98 ReclaimPhase(); 99 thread_list->ResumeAll(); 100 } 101 ATRACE_END(); 102 RegisterPause(NanoTime() - pause_start); 103 } else { 104 CHECK(!Locks::mutator_lock_->IsExclusiveHeld(self)); 105 Thread* self = Thread::Current(); 106 { 107 ReaderMutexLock mu(self, *Locks::mutator_lock_); 108 MarkingPhase(); 109 } 110 bool done = false; 111 while (!done) { 112 uint64_t pause_start = NanoTime(); 113 ATRACE_BEGIN("Suspending mutator threads"); 114 thread_list->SuspendAll(); 115 ATRACE_END(); 116 ATRACE_BEGIN("All mutator threads suspended"); 117 done = HandleDirtyObjectsPhase(); 118 if (done) { 119 GetHeap()->RevokeAllThreadLocalBuffers(); 120 } 121 ATRACE_END(); 122 uint64_t pause_end = NanoTime(); 123 ATRACE_BEGIN("Resuming mutator threads"); 124 thread_list->ResumeAll(); 125 ATRACE_END(); 126 RegisterPause(pause_end - pause_start); 127 } 128 { 129 ReaderMutexLock mu(self, *Locks::mutator_lock_); 130 ReclaimPhase(); 131 } 132 } 133 FinishPhase(); 134 uint64_t end_time = NanoTime(); 135 duration_ns_ = end_time - start_time; 136 total_time_ns_ += GetDurationNs(); 137 for (uint64_t pause_time : pause_times_) { 138 pause_histogram_.AddValue(pause_time / 1000); 139 } 140} 141 142void GarbageCollector::SwapBitmaps() { 143 // Swap the live and mark bitmaps for each alloc space. This is needed since sweep re-swaps 144 // these bitmaps. The bitmap swapping is an optimization so that we do not need to clear the live 145 // bits of dead objects in the live bitmap. 146 const GcType gc_type = GetGcType(); 147 for (const auto& space : GetHeap()->GetContinuousSpaces()) { 148 // We never allocate into zygote spaces. 149 if (space->GetGcRetentionPolicy() == space::kGcRetentionPolicyAlwaysCollect || 150 (gc_type == kGcTypeFull && 151 space->GetGcRetentionPolicy() == space::kGcRetentionPolicyFullCollect)) { 152 accounting::SpaceBitmap* live_bitmap = space->GetLiveBitmap(); 153 accounting::SpaceBitmap* mark_bitmap = space->GetMarkBitmap(); 154 if (live_bitmap != nullptr && live_bitmap != mark_bitmap) { 155 heap_->GetLiveBitmap()->ReplaceBitmap(live_bitmap, mark_bitmap); 156 heap_->GetMarkBitmap()->ReplaceBitmap(mark_bitmap, live_bitmap); 157 CHECK(space->IsContinuousMemMapAllocSpace()); 158 space->AsContinuousMemMapAllocSpace()->SwapBitmaps(); 159 } 160 } 161 } 162 for (const auto& disc_space : GetHeap()->GetDiscontinuousSpaces()) { 163 space::LargeObjectSpace* space = down_cast<space::LargeObjectSpace*>(disc_space); 164 accounting::ObjectSet* live_set = space->GetLiveObjects(); 165 accounting::ObjectSet* mark_set = space->GetMarkObjects(); 166 heap_->GetLiveBitmap()->ReplaceObjectSet(live_set, mark_set); 167 heap_->GetMarkBitmap()->ReplaceObjectSet(mark_set, live_set); 168 down_cast<space::LargeObjectSpace*>(space)->SwapBitmaps(); 169 } 170} 171 172} // namespace collector 173} // namespace gc 174} // namespace art 175