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