immune_spaces.cc revision df0a8275abadc96a6363b59f31c64981571d6ed9
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
19763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier#include "gc/space/space-inl.h"
20763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier#include "mirror/object.h"
21df0a8275abadc96a6363b59f31c64981571d6ed9Mathieu Chartier#include "oat_file.h"
22763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier
23763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartiernamespace art {
24763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartiernamespace gc {
25763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartiernamespace collector {
26763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier
27763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartiervoid ImmuneSpaces::Reset() {
28763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier  spaces_.clear();
29763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier  largest_immune_region_.Reset();
30763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier}
31763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier
32763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartiervoid ImmuneSpaces::CreateLargestImmuneRegion() {
33763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier  uintptr_t best_begin = 0u;
34763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier  uintptr_t best_end = 0u;
35763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier  uintptr_t cur_begin = 0u;
36763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier  uintptr_t cur_end = 0u;
37763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier  // TODO: If the last space is an image space, we may include its oat file in the immune region.
38763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier  // This could potentially hide heap corruption bugs if there is invalid pointers that point into
39763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier  // the boot oat code
40763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier  for (space::ContinuousSpace* space : GetSpaces()) {
41763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier    uintptr_t space_begin = reinterpret_cast<uintptr_t>(space->Begin());
42763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier    uintptr_t space_end = reinterpret_cast<uintptr_t>(space->Limit());
43763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier    if (space->IsImageSpace()) {
44763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier      // For the boot image, the boot oat file is always directly after. For app images it may not
45763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier      // be if the app image was mapped at a random address.
46763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier      space::ImageSpace* image_space = space->AsImageSpace();
47763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier      // Update the end to include the other non-heap sections.
48763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier      space_end = RoundUp(reinterpret_cast<uintptr_t>(image_space->GetImageEnd()), kPageSize);
49df0a8275abadc96a6363b59f31c64981571d6ed9Mathieu Chartier      // For the app image case, GetOatFileBegin is where the oat file was mapped during image
50df0a8275abadc96a6363b59f31c64981571d6ed9Mathieu Chartier      // creation, the actual oat file could be somewhere else.
51df0a8275abadc96a6363b59f31c64981571d6ed9Mathieu Chartier      const OatFile* const image_oat_file = image_space->GetOatFile();
52df0a8275abadc96a6363b59f31c64981571d6ed9Mathieu Chartier      if (image_oat_file != nullptr) {
53df0a8275abadc96a6363b59f31c64981571d6ed9Mathieu Chartier        uintptr_t oat_begin = reinterpret_cast<uintptr_t>(image_oat_file->Begin());
54df0a8275abadc96a6363b59f31c64981571d6ed9Mathieu Chartier        uintptr_t oat_end = reinterpret_cast<uintptr_t>(image_oat_file->End());
55df0a8275abadc96a6363b59f31c64981571d6ed9Mathieu Chartier        if (space_end == oat_begin) {
56df0a8275abadc96a6363b59f31c64981571d6ed9Mathieu Chartier          DCHECK_GE(oat_end, oat_begin);
57df0a8275abadc96a6363b59f31c64981571d6ed9Mathieu Chartier          space_end = oat_end;
58df0a8275abadc96a6363b59f31c64981571d6ed9Mathieu Chartier        }
59763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier      }
60763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier    }
61763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier    if (cur_begin == 0u) {
62763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier      cur_begin = space_begin;
63763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier      cur_end = space_end;
64763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier    } else if (cur_end == space_begin) {
65763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier      // Extend current region.
66763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier      cur_end = space_end;
67763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier    } else {
68763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier      // Reset.
69763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier      cur_begin = 0;
70763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier      cur_end = 0;
71763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier    }
72763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier    if (cur_end - cur_begin > best_end - best_begin) {
73763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier      // Improvement, update the best range.
74763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier      best_begin = cur_begin;
75763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier      best_end = cur_end;
76763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier    }
77763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier  }
78763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier  largest_immune_region_.SetBegin(reinterpret_cast<mirror::Object*>(best_begin));
79763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier  largest_immune_region_.SetEnd(reinterpret_cast<mirror::Object*>(best_end));
80df0a8275abadc96a6363b59f31c64981571d6ed9Mathieu Chartier  VLOG(gc) << "Immune region " << largest_immune_region_.Begin() << "-"
81df0a8275abadc96a6363b59f31c64981571d6ed9Mathieu Chartier           << largest_immune_region_.End();
82763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier}
83763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier
84763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartiervoid ImmuneSpaces::AddSpace(space::ContinuousSpace* space) {
85763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier  DCHECK(spaces_.find(space) == spaces_.end()) << *space;
86763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier  // Bind live to mark bitmap if necessary.
87763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier  if (space->GetLiveBitmap() != space->GetMarkBitmap()) {
88763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier    CHECK(space->IsContinuousMemMapAllocSpace());
89763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier    space->AsContinuousMemMapAllocSpace()->BindLiveToMarkBitmap();
90763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier  }
91763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier  spaces_.insert(space);
92763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier  CreateLargestImmuneRegion();
93763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier}
94763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier
95763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartierbool ImmuneSpaces::CompareByBegin::operator()(space::ContinuousSpace* a, space::ContinuousSpace* b)
96763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier    const {
97763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier  return a->Begin() < b->Begin();
98763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier}
99763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier
100763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartierbool ImmuneSpaces::ContainsSpace(space::ContinuousSpace* space) const {
101763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier  return spaces_.find(space) != spaces_.end();
102763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier}
103763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier
104763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier}  // namespace collector
105763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier}  // namespace gc
106763a31ed7a2bfad22a9cb07f5301a71c0f97ca49Mathieu Chartier}  // namespace art
107