Home | History | Annotate | Download | only in collector
      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 <vector>
     20 #include <tuple>
     21 
     22 #include "gc/space/space-inl.h"
     23 #include "mirror/object.h"
     24 #include "oat_file.h"
     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;
     38   uintptr_t best_heap_size = 0u;
     39   uintptr_t cur_begin = 0u;
     40   uintptr_t cur_end = 0u;
     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;
     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);
     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) {
     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));
     60       }
     61     }
     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;
     87     }
     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       }
     98     }
     99   }
    100   largest_immune_region_.SetBegin(reinterpret_cast<mirror::Object*>(best_begin));
    101   largest_immune_region_.SetEnd(reinterpret_cast<mirror::Object*>(best_end));
    102   VLOG(collector) << "Immune region " << largest_immune_region_.Begin() << "-"
    103                   << largest_immune_region_.End();
    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
    129