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