1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker * Copyright (C) 2015 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker *
4*795d594fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker *
8*795d594fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker *
10*795d594fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker */
16*795d594fSAndroid Build Coastguard Worker
17*795d594fSAndroid Build Coastguard Worker #include "immune_spaces.h"
18*795d594fSAndroid Build Coastguard Worker
19*795d594fSAndroid Build Coastguard Worker #include <tuple>
20*795d594fSAndroid Build Coastguard Worker #include <vector>
21*795d594fSAndroid Build Coastguard Worker
22*795d594fSAndroid Build Coastguard Worker #include "base/logging.h" // For VLOG.
23*795d594fSAndroid Build Coastguard Worker #include "gc/space/space-inl.h"
24*795d594fSAndroid Build Coastguard Worker #include "mirror/object.h"
25*795d594fSAndroid Build Coastguard Worker #include "oat/oat_file.h"
26*795d594fSAndroid Build Coastguard Worker
27*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN {
28*795d594fSAndroid Build Coastguard Worker namespace gc {
29*795d594fSAndroid Build Coastguard Worker namespace collector {
30*795d594fSAndroid Build Coastguard Worker
Reset()31*795d594fSAndroid Build Coastguard Worker void ImmuneSpaces::Reset() {
32*795d594fSAndroid Build Coastguard Worker spaces_.clear();
33*795d594fSAndroid Build Coastguard Worker largest_immune_region_.Reset();
34*795d594fSAndroid Build Coastguard Worker }
35*795d594fSAndroid Build Coastguard Worker
CreateLargestImmuneRegion()36*795d594fSAndroid Build Coastguard Worker void ImmuneSpaces::CreateLargestImmuneRegion() {
37*795d594fSAndroid Build Coastguard Worker uintptr_t best_begin = 0u;
38*795d594fSAndroid Build Coastguard Worker uintptr_t best_end = 0u;
39*795d594fSAndroid Build Coastguard Worker uintptr_t best_heap_size = 0u;
40*795d594fSAndroid Build Coastguard Worker uintptr_t cur_begin = 0u;
41*795d594fSAndroid Build Coastguard Worker uintptr_t cur_end = 0u;
42*795d594fSAndroid Build Coastguard Worker uintptr_t cur_heap_size = 0u;
43*795d594fSAndroid Build Coastguard Worker using Interval = std::tuple</*start*/uintptr_t, /*end*/uintptr_t, /*is_heap*/bool>;
44*795d594fSAndroid Build Coastguard Worker std::vector<Interval> intervals;
45*795d594fSAndroid Build Coastguard Worker for (space::ContinuousSpace* space : GetSpaces()) {
46*795d594fSAndroid Build Coastguard Worker uintptr_t space_begin = reinterpret_cast<uintptr_t>(space->Begin());
47*795d594fSAndroid Build Coastguard Worker uintptr_t space_end = reinterpret_cast<uintptr_t>(space->Limit());
48*795d594fSAndroid Build Coastguard Worker if (space->IsImageSpace()) {
49*795d594fSAndroid Build Coastguard Worker // For the boot image, the boot oat file is always directly after. For app images it may not
50*795d594fSAndroid Build Coastguard Worker // be if the app image was mapped at a random address.
51*795d594fSAndroid Build Coastguard Worker space::ImageSpace* image_space = space->AsImageSpace();
52*795d594fSAndroid Build Coastguard Worker // Update the end to include the other non-heap sections.
53*795d594fSAndroid Build Coastguard Worker space_end = RoundUp(reinterpret_cast<uintptr_t>(image_space->GetImageEnd()),
54*795d594fSAndroid Build Coastguard Worker kElfSegmentAlignment);
55*795d594fSAndroid Build Coastguard Worker // For the app image case, GetOatFileBegin is where the oat file was mapped during image
56*795d594fSAndroid Build Coastguard Worker // creation, the actual oat file could be somewhere else.
57*795d594fSAndroid Build Coastguard Worker const OatFile* const image_oat_file = image_space->GetOatFile();
58*795d594fSAndroid Build Coastguard Worker if (image_oat_file != nullptr) {
59*795d594fSAndroid Build Coastguard Worker intervals.push_back(Interval(reinterpret_cast<uintptr_t>(image_oat_file->Begin()),
60*795d594fSAndroid Build Coastguard Worker reinterpret_cast<uintptr_t>(image_oat_file->End()),
61*795d594fSAndroid Build Coastguard Worker /*image=*/false));
62*795d594fSAndroid Build Coastguard Worker }
63*795d594fSAndroid Build Coastguard Worker }
64*795d594fSAndroid Build Coastguard Worker intervals.push_back(Interval(space_begin, space_end, /*is_heap*/true));
65*795d594fSAndroid Build Coastguard Worker }
66*795d594fSAndroid Build Coastguard Worker std::sort(intervals.begin(), intervals.end());
67*795d594fSAndroid Build Coastguard Worker // Intervals are already sorted by begin, if a new interval begins at the end of the current
68*795d594fSAndroid Build Coastguard Worker // region then we append, otherwise we restart the current interval. To prevent starting an
69*795d594fSAndroid Build Coastguard Worker // interval on an oat file, ignore oat files that are not extending an existing interval.
70*795d594fSAndroid Build Coastguard Worker // If the total number of image bytes in the current interval is larger than the current best
71*795d594fSAndroid Build Coastguard Worker // one, then we set the best one to be the current one.
72*795d594fSAndroid Build Coastguard Worker for (const Interval& interval : intervals) {
73*795d594fSAndroid Build Coastguard Worker const uintptr_t begin = std::get<0>(interval);
74*795d594fSAndroid Build Coastguard Worker const uintptr_t end = std::get<1>(interval);
75*795d594fSAndroid Build Coastguard Worker const bool is_heap = std::get<2>(interval);
76*795d594fSAndroid Build Coastguard Worker VLOG(collector) << "Interval " << reinterpret_cast<const void*>(begin) << "-"
77*795d594fSAndroid Build Coastguard Worker << reinterpret_cast<const void*>(end) << " is_heap=" << is_heap;
78*795d594fSAndroid Build Coastguard Worker DCHECK_GE(end, begin);
79*795d594fSAndroid Build Coastguard Worker DCHECK_GE(begin, cur_end);
80*795d594fSAndroid Build Coastguard Worker // New interval is not at the end of the current one, start a new interval if we are a heap
81*795d594fSAndroid Build Coastguard Worker // interval. Otherwise continue since we never start a new region with non image intervals.
82*795d594fSAndroid Build Coastguard Worker if (begin != cur_end) {
83*795d594fSAndroid Build Coastguard Worker if (!is_heap) {
84*795d594fSAndroid Build Coastguard Worker continue;
85*795d594fSAndroid Build Coastguard Worker }
86*795d594fSAndroid Build Coastguard Worker // Not extending, reset the region.
87*795d594fSAndroid Build Coastguard Worker cur_begin = begin;
88*795d594fSAndroid Build Coastguard Worker cur_heap_size = 0;
89*795d594fSAndroid Build Coastguard Worker }
90*795d594fSAndroid Build Coastguard Worker cur_end = end;
91*795d594fSAndroid Build Coastguard Worker if (is_heap) {
92*795d594fSAndroid Build Coastguard Worker // Only update if the total number of image bytes is greater than the current best one.
93*795d594fSAndroid Build Coastguard Worker // We don't want to count the oat file bytes since these contain no java objects.
94*795d594fSAndroid Build Coastguard Worker cur_heap_size += end - begin;
95*795d594fSAndroid Build Coastguard Worker if (cur_heap_size > best_heap_size) {
96*795d594fSAndroid Build Coastguard Worker best_begin = cur_begin;
97*795d594fSAndroid Build Coastguard Worker best_end = cur_end;
98*795d594fSAndroid Build Coastguard Worker best_heap_size = cur_heap_size;
99*795d594fSAndroid Build Coastguard Worker }
100*795d594fSAndroid Build Coastguard Worker }
101*795d594fSAndroid Build Coastguard Worker }
102*795d594fSAndroid Build Coastguard Worker largest_immune_region_.SetBegin(reinterpret_cast<mirror::Object*>(best_begin));
103*795d594fSAndroid Build Coastguard Worker largest_immune_region_.SetEnd(reinterpret_cast<mirror::Object*>(best_end));
104*795d594fSAndroid Build Coastguard Worker VLOG(collector) << "Immune region " << largest_immune_region_.Begin() << "-"
105*795d594fSAndroid Build Coastguard Worker << largest_immune_region_.End();
106*795d594fSAndroid Build Coastguard Worker }
107*795d594fSAndroid Build Coastguard Worker
AddSpace(space::ContinuousSpace * space)108*795d594fSAndroid Build Coastguard Worker void ImmuneSpaces::AddSpace(space::ContinuousSpace* space) {
109*795d594fSAndroid Build Coastguard Worker DCHECK(spaces_.find(space) == spaces_.end()) << *space;
110*795d594fSAndroid Build Coastguard Worker // Bind live to mark bitmap if necessary.
111*795d594fSAndroid Build Coastguard Worker if (space->GetLiveBitmap() != nullptr && !space->HasBoundBitmaps()) {
112*795d594fSAndroid Build Coastguard Worker CHECK(space->IsContinuousMemMapAllocSpace());
113*795d594fSAndroid Build Coastguard Worker space->AsContinuousMemMapAllocSpace()->BindLiveToMarkBitmap();
114*795d594fSAndroid Build Coastguard Worker }
115*795d594fSAndroid Build Coastguard Worker spaces_.insert(space);
116*795d594fSAndroid Build Coastguard Worker CreateLargestImmuneRegion();
117*795d594fSAndroid Build Coastguard Worker }
118*795d594fSAndroid Build Coastguard Worker
operator ()(space::ContinuousSpace * a,space::ContinuousSpace * b) const119*795d594fSAndroid Build Coastguard Worker bool ImmuneSpaces::CompareByBegin::operator()(space::ContinuousSpace* a, space::ContinuousSpace* b)
120*795d594fSAndroid Build Coastguard Worker const {
121*795d594fSAndroid Build Coastguard Worker return a->Begin() < b->Begin();
122*795d594fSAndroid Build Coastguard Worker }
123*795d594fSAndroid Build Coastguard Worker
ContainsSpace(space::ContinuousSpace * space) const124*795d594fSAndroid Build Coastguard Worker bool ImmuneSpaces::ContainsSpace(space::ContinuousSpace* space) const {
125*795d594fSAndroid Build Coastguard Worker return spaces_.find(space) != spaces_.end();
126*795d594fSAndroid Build Coastguard Worker }
127*795d594fSAndroid Build Coastguard Worker
128*795d594fSAndroid Build Coastguard Worker } // namespace collector
129*795d594fSAndroid Build Coastguard Worker } // namespace gc
130*795d594fSAndroid Build Coastguard Worker } // namespace art
131