1763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier/*
2763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier * Copyright (C) 2015 The Android Open Source Project
3763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier *
4763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier * Licensed under the Apache License, Version 2.0 (the "License");
5763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier * you may not use this file except in compliance with the License.
6763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier * You may obtain a copy of the License at
7763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier *
8763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier *      http://www.apache.org/licenses/LICENSE-2.0
9763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier *
10763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier * Unless required by applicable law or agreed to in writing, software
11763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier * distributed under the License is distributed on an "AS IS" BASIS,
12763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier * See the License for the specific language governing permissions and
14763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier * limitations under the License.
15763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier */
16763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier
17763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier#include "immune_spaces.h"
18763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier
190cc2a92374ef14b0e2104b9d4ea148750b657694Mathieu Chartier#include <vector>
200cc2a92374ef14b0e2104b9d4ea148750b657694Mathieu Chartier#include <tuple>
210cc2a92374ef14b0e2104b9d4ea148750b657694Mathieu Chartier
22763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier#include "gc/space/space-inl.h"
23763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier#include "mirror/object.h"
24df0a8275abadc96a6363b59f31c64981571d6ed9Mathieu Chartier#include "oat_file.h"
25763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier
26763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartiernamespace art {
27763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartiernamespace gc {
28763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartiernamespace collector {
29763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier
30763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartiervoid ImmuneSpaces::Reset() {
31763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier  spaces_.clear();
32763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier  largest_immune_region_.Reset();
33763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier}
34763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier
35763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartiervoid ImmuneSpaces::CreateLargestImmuneRegion() {
36763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier  uintptr_t best_begin = 0u;
37763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier  uintptr_t best_end = 0u;
380cc2a92374ef14b0e2104b9d4ea148750b657694Mathieu Chartier  uintptr_t best_heap_size = 0u;
39763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier  uintptr_t cur_begin = 0u;
40763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier  uintptr_t cur_end = 0u;
410cc2a92374ef14b0e2104b9d4ea148750b657694Mathieu Chartier  uintptr_t cur_heap_size = 0u;
420cc2a92374ef14b0e2104b9d4ea148750b657694Mathieu Chartier  using Interval = std::tuple</*start*/uintptr_t, /*end*/uintptr_t, /*is_heap*/bool>;
430cc2a92374ef14b0e2104b9d4ea148750b657694Mathieu Chartier  std::vector<Interval> intervals;
44763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier  for (space::ContinuousSpace* space : GetSpaces()) {
45763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier    uintptr_t space_begin = reinterpret_cast<uintptr_t>(space->Begin());
46763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier    uintptr_t space_end = reinterpret_cast<uintptr_t>(space->Limit());
47763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier    if (space->IsImageSpace()) {
48763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier      // For the boot image, the boot oat file is always directly after. For app images it may not
49763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier      // be if the app image was mapped at a random address.
50763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier      space::ImageSpace* image_space = space->AsImageSpace();
51763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier      // Update the end to include the other non-heap sections.
52763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier      space_end = RoundUp(reinterpret_cast<uintptr_t>(image_space->GetImageEnd()), kPageSize);
53df0a8275abadc96a6363b59f31c64981571d6ed9Mathieu Chartier      // For the app image case, GetOatFileBegin is where the oat file was mapped during image
54df0a8275abadc96a6363b59f31c64981571d6ed9Mathieu Chartier      // creation, the actual oat file could be somewhere else.
55df0a8275abadc96a6363b59f31c64981571d6ed9Mathieu Chartier      const OatFile* const image_oat_file = image_space->GetOatFile();
56df0a8275abadc96a6363b59f31c64981571d6ed9Mathieu Chartier      if (image_oat_file != nullptr) {
570cc2a92374ef14b0e2104b9d4ea148750b657694Mathieu Chartier        intervals.push_back(Interval(reinterpret_cast<uintptr_t>(image_oat_file->Begin()),
580cc2a92374ef14b0e2104b9d4ea148750b657694Mathieu Chartier                                     reinterpret_cast<uintptr_t>(image_oat_file->End()),
590cc2a92374ef14b0e2104b9d4ea148750b657694Mathieu Chartier                                     /*image*/false));
60763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier      }
61763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier    }
620cc2a92374ef14b0e2104b9d4ea148750b657694Mathieu Chartier    intervals.push_back(Interval(space_begin, space_end, /*is_heap*/true));
630cc2a92374ef14b0e2104b9d4ea148750b657694Mathieu Chartier  }
640cc2a92374ef14b0e2104b9d4ea148750b657694Mathieu Chartier  std::sort(intervals.begin(), intervals.end());
650cc2a92374ef14b0e2104b9d4ea148750b657694Mathieu Chartier  // Intervals are already sorted by begin, if a new interval begins at the end of the current
660cc2a92374ef14b0e2104b9d4ea148750b657694Mathieu Chartier  // region then we append, otherwise we restart the current interval. To prevent starting an
670cc2a92374ef14b0e2104b9d4ea148750b657694Mathieu Chartier  // interval on an oat file, ignore oat files that are not extending an existing interval.
680cc2a92374ef14b0e2104b9d4ea148750b657694Mathieu Chartier  // If the total number of image bytes in the current interval is larger than the current best
690cc2a92374ef14b0e2104b9d4ea148750b657694Mathieu Chartier  // one, then we set the best one to be the current one.
700cc2a92374ef14b0e2104b9d4ea148750b657694Mathieu Chartier  for (const Interval& interval : intervals) {
710cc2a92374ef14b0e2104b9d4ea148750b657694Mathieu Chartier    const uintptr_t begin = std::get<0>(interval);
720cc2a92374ef14b0e2104b9d4ea148750b657694Mathieu Chartier    const uintptr_t end = std::get<1>(interval);
730cc2a92374ef14b0e2104b9d4ea148750b657694Mathieu Chartier    const bool is_heap = std::get<2>(interval);
740cc2a92374ef14b0e2104b9d4ea148750b657694Mathieu Chartier    VLOG(collector) << "Interval " << reinterpret_cast<const void*>(begin) << "-"
750cc2a92374ef14b0e2104b9d4ea148750b657694Mathieu Chartier                    << reinterpret_cast<const void*>(end) << " is_heap=" << is_heap;
760cc2a92374ef14b0e2104b9d4ea148750b657694Mathieu Chartier    DCHECK_GE(end, begin);
770cc2a92374ef14b0e2104b9d4ea148750b657694Mathieu Chartier    DCHECK_GE(begin, cur_end);
780cc2a92374ef14b0e2104b9d4ea148750b657694Mathieu Chartier    // New interval is not at the end of the current one, start a new interval if we are a heap
790cc2a92374ef14b0e2104b9d4ea148750b657694Mathieu Chartier    // interval. Otherwise continue since we never start a new region with non image intervals.
800cc2a92374ef14b0e2104b9d4ea148750b657694Mathieu Chartier    if (begin != cur_end) {
810cc2a92374ef14b0e2104b9d4ea148750b657694Mathieu Chartier      if (!is_heap) {
820cc2a92374ef14b0e2104b9d4ea148750b657694Mathieu Chartier        continue;
830cc2a92374ef14b0e2104b9d4ea148750b657694Mathieu Chartier      }
840cc2a92374ef14b0e2104b9d4ea148750b657694Mathieu Chartier      // Not extending, reset the region.
850cc2a92374ef14b0e2104b9d4ea148750b657694Mathieu Chartier      cur_begin = begin;
860cc2a92374ef14b0e2104b9d4ea148750b657694Mathieu Chartier      cur_heap_size = 0;
87763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier    }
880cc2a92374ef14b0e2104b9d4ea148750b657694Mathieu Chartier    cur_end = end;
890cc2a92374ef14b0e2104b9d4ea148750b657694Mathieu Chartier    if (is_heap) {
900cc2a92374ef14b0e2104b9d4ea148750b657694Mathieu Chartier      // Only update if the total number of image bytes is greater than the current best one.
910cc2a92374ef14b0e2104b9d4ea148750b657694Mathieu Chartier      // We don't want to count the oat file bytes since these contain no java objects.
920cc2a92374ef14b0e2104b9d4ea148750b657694Mathieu Chartier      cur_heap_size += end - begin;
930cc2a92374ef14b0e2104b9d4ea148750b657694Mathieu Chartier      if (cur_heap_size > best_heap_size) {
940cc2a92374ef14b0e2104b9d4ea148750b657694Mathieu Chartier        best_begin = cur_begin;
950cc2a92374ef14b0e2104b9d4ea148750b657694Mathieu Chartier        best_end = cur_end;
960cc2a92374ef14b0e2104b9d4ea148750b657694Mathieu Chartier        best_heap_size = cur_heap_size;
970cc2a92374ef14b0e2104b9d4ea148750b657694Mathieu Chartier      }
98763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier    }
99763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier  }
100763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier  largest_immune_region_.SetBegin(reinterpret_cast<mirror::Object*>(best_begin));
101763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier  largest_immune_region_.SetEnd(reinterpret_cast<mirror::Object*>(best_end));
102a6e1c126299586932ecd3c1133a55a6f8e1107fcMathieu Chartier  VLOG(collector) << "Immune region " << largest_immune_region_.Begin() << "-"
103a6e1c126299586932ecd3c1133a55a6f8e1107fcMathieu Chartier                  << largest_immune_region_.End();
104763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier}
105763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier
106763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartiervoid ImmuneSpaces::AddSpace(space::ContinuousSpace* space) {
107763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier  DCHECK(spaces_.find(space) == spaces_.end()) << *space;
108763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier  // Bind live to mark bitmap if necessary.
109763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier  if (space->GetLiveBitmap() != space->GetMarkBitmap()) {
110763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier    CHECK(space->IsContinuousMemMapAllocSpace());
111763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier    space->AsContinuousMemMapAllocSpace()->BindLiveToMarkBitmap();
112763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier  }
113763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier  spaces_.insert(space);
114763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier  CreateLargestImmuneRegion();
115763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier}
116763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier
117763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartierbool ImmuneSpaces::CompareByBegin::operator()(space::ContinuousSpace* a, space::ContinuousSpace* b)
118763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier    const {
119763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier  return a->Begin() < b->Begin();
120763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier}
121763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier
122763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartierbool ImmuneSpaces::ContainsSpace(space::ContinuousSpace* space) const {
123763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier  return spaces_.find(space) != spaces_.end();
124763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier}
125763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier
126763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier}  // namespace collector
127763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier}  // namespace gc
128763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier}  // namespace art
129