1 /* 2 * Copyright (C) 2015 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 "immune_spaces.h" 18 19 #include <tuple> 20 #include <vector> 21 22 #include "base/logging.h" // For VLOG. 23 #include "gc/space/space-inl.h" 24 #include "mirror/object.h" 25 #include "oat_file.h" 26 27 namespace art { 28 namespace gc { 29 namespace collector { 30 31 void ImmuneSpaces::Reset() { 32 spaces_.clear(); 33 largest_immune_region_.Reset(); 34 } 35 36 void ImmuneSpaces::CreateLargestImmuneRegion() { 37 uintptr_t best_begin = 0u; 38 uintptr_t best_end = 0u; 39 uintptr_t best_heap_size = 0u; 40 uintptr_t cur_begin = 0u; 41 uintptr_t cur_end = 0u; 42 uintptr_t cur_heap_size = 0u; 43 using Interval = std::tuple</*start*/uintptr_t, /*end*/uintptr_t, /*is_heap*/bool>; 44 std::vector<Interval> intervals; 45 for (space::ContinuousSpace* space : GetSpaces()) { 46 uintptr_t space_begin = reinterpret_cast<uintptr_t>(space->Begin()); 47 uintptr_t space_end = reinterpret_cast<uintptr_t>(space->Limit()); 48 if (space->IsImageSpace()) { 49 // For the boot image, the boot oat file is always directly after. For app images it may not 50 // be if the app image was mapped at a random address. 51 space::ImageSpace* image_space = space->AsImageSpace(); 52 // Update the end to include the other non-heap sections. 53 space_end = RoundUp(reinterpret_cast<uintptr_t>(image_space->GetImageEnd()), kPageSize); 54 // For the app image case, GetOatFileBegin is where the oat file was mapped during image 55 // creation, the actual oat file could be somewhere else. 56 const OatFile* const image_oat_file = image_space->GetOatFile(); 57 if (image_oat_file != nullptr) { 58 intervals.push_back(Interval(reinterpret_cast<uintptr_t>(image_oat_file->Begin()), 59 reinterpret_cast<uintptr_t>(image_oat_file->End()), 60 /*image=*/false)); 61 } 62 } 63 intervals.push_back(Interval(space_begin, space_end, /*is_heap*/true)); 64 } 65 std::sort(intervals.begin(), intervals.end()); 66 // Intervals are already sorted by begin, if a new interval begins at the end of the current 67 // region then we append, otherwise we restart the current interval. To prevent starting an 68 // interval on an oat file, ignore oat files that are not extending an existing interval. 69 // If the total number of image bytes in the current interval is larger than the current best 70 // one, then we set the best one to be the current one. 71 for (const Interval& interval : intervals) { 72 const uintptr_t begin = std::get<0>(interval); 73 const uintptr_t end = std::get<1>(interval); 74 const bool is_heap = std::get<2>(interval); 75 VLOG(collector) << "Interval " << reinterpret_cast<const void*>(begin) << "-" 76 << reinterpret_cast<const void*>(end) << " is_heap=" << is_heap; 77 DCHECK_GE(end, begin); 78 DCHECK_GE(begin, cur_end); 79 // New interval is not at the end of the current one, start a new interval if we are a heap 80 // interval. Otherwise continue since we never start a new region with non image intervals. 81 if (begin != cur_end) { 82 if (!is_heap) { 83 continue; 84 } 85 // Not extending, reset the region. 86 cur_begin = begin; 87 cur_heap_size = 0; 88 } 89 cur_end = end; 90 if (is_heap) { 91 // Only update if the total number of image bytes is greater than the current best one. 92 // We don't want to count the oat file bytes since these contain no java objects. 93 cur_heap_size += end - begin; 94 if (cur_heap_size > best_heap_size) { 95 best_begin = cur_begin; 96 best_end = cur_end; 97 best_heap_size = cur_heap_size; 98 } 99 } 100 } 101 largest_immune_region_.SetBegin(reinterpret_cast<mirror::Object*>(best_begin)); 102 largest_immune_region_.SetEnd(reinterpret_cast<mirror::Object*>(best_end)); 103 VLOG(collector) << "Immune region " << largest_immune_region_.Begin() << "-" 104 << largest_immune_region_.End(); 105 } 106 107 void ImmuneSpaces::AddSpace(space::ContinuousSpace* space) { 108 DCHECK(spaces_.find(space) == spaces_.end()) << *space; 109 // Bind live to mark bitmap if necessary. 110 if (space->GetLiveBitmap() != space->GetMarkBitmap()) { 111 CHECK(space->IsContinuousMemMapAllocSpace()); 112 space->AsContinuousMemMapAllocSpace()->BindLiveToMarkBitmap(); 113 } 114 spaces_.insert(space); 115 CreateLargestImmuneRegion(); 116 } 117 118 bool ImmuneSpaces::CompareByBegin::operator()(space::ContinuousSpace* a, space::ContinuousSpace* b) 119 const { 120 return a->Begin() < b->Begin(); 121 } 122 123 bool ImmuneSpaces::ContainsSpace(space::ContinuousSpace* space) const { 124 return spaces_.find(space) != spaces_.end(); 125 } 126 127 } // namespace collector 128 } // namespace gc 129 } // namespace art 130