/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "immune_spaces.h"

#include <tuple>
#include <vector>

#include "base/logging.h"  // For VLOG.
#include "gc/space/space-inl.h"
#include "mirror/object.h"
#include "oat_file.h"

namespace art {
namespace gc {
namespace collector {

void ImmuneSpaces::Reset() {
  spaces_.clear();
  largest_immune_region_.Reset();
}

void ImmuneSpaces::CreateLargestImmuneRegion() {
  uintptr_t best_begin = 0u;
  uintptr_t best_end = 0u;
  uintptr_t best_heap_size = 0u;
  uintptr_t cur_begin = 0u;
  uintptr_t cur_end = 0u;
  uintptr_t cur_heap_size = 0u;
  using Interval = std::tuple</*start*/uintptr_t, /*end*/uintptr_t, /*is_heap*/bool>;
  std::vector<Interval> intervals;
  for (space::ContinuousSpace* space : GetSpaces()) {
    uintptr_t space_begin = reinterpret_cast<uintptr_t>(space->Begin());
    uintptr_t space_end = reinterpret_cast<uintptr_t>(space->Limit());
    if (space->IsImageSpace()) {
      // For the boot image, the boot oat file is always directly after. For app images it may not
      // be if the app image was mapped at a random address.
      space::ImageSpace* image_space = space->AsImageSpace();
      // Update the end to include the other non-heap sections.
      space_end = RoundUp(reinterpret_cast<uintptr_t>(image_space->GetImageEnd()), kPageSize);
      // For the app image case, GetOatFileBegin is where the oat file was mapped during image
      // creation, the actual oat file could be somewhere else.
      const OatFile* const image_oat_file = image_space->GetOatFile();
      if (image_oat_file != nullptr) {
        intervals.push_back(Interval(reinterpret_cast<uintptr_t>(image_oat_file->Begin()),
                                     reinterpret_cast<uintptr_t>(image_oat_file->End()),
                                     /*image=*/false));
      }
    }
    intervals.push_back(Interval(space_begin, space_end, /*is_heap*/true));
  }
  std::sort(intervals.begin(), intervals.end());
  // Intervals are already sorted by begin, if a new interval begins at the end of the current
  // region then we append, otherwise we restart the current interval. To prevent starting an
  // interval on an oat file, ignore oat files that are not extending an existing interval.
  // If the total number of image bytes in the current interval is larger than the current best
  // one, then we set the best one to be the current one.
  for (const Interval& interval : intervals) {
    const uintptr_t begin = std::get<0>(interval);
    const uintptr_t end = std::get<1>(interval);
    const bool is_heap = std::get<2>(interval);
    VLOG(collector) << "Interval " << reinterpret_cast<const void*>(begin) << "-"
                    << reinterpret_cast<const void*>(end) << " is_heap=" << is_heap;
    DCHECK_GE(end, begin);
    DCHECK_GE(begin, cur_end);
    // New interval is not at the end of the current one, start a new interval if we are a heap
    // interval. Otherwise continue since we never start a new region with non image intervals.
    if (begin != cur_end) {
      if (!is_heap) {
        continue;
      }
      // Not extending, reset the region.
      cur_begin = begin;
      cur_heap_size = 0;
    }
    cur_end = end;
    if (is_heap) {
      // Only update if the total number of image bytes is greater than the current best one.
      // We don't want to count the oat file bytes since these contain no java objects.
      cur_heap_size += end - begin;
      if (cur_heap_size > best_heap_size) {
        best_begin = cur_begin;
        best_end = cur_end;
        best_heap_size = cur_heap_size;
      }
    }
  }
  largest_immune_region_.SetBegin(reinterpret_cast<mirror::Object*>(best_begin));
  largest_immune_region_.SetEnd(reinterpret_cast<mirror::Object*>(best_end));
  VLOG(collector) << "Immune region " << largest_immune_region_.Begin() << "-"
                  << largest_immune_region_.End();
}

void ImmuneSpaces::AddSpace(space::ContinuousSpace* space) {
  DCHECK(spaces_.find(space) == spaces_.end()) << *space;
  // Bind live to mark bitmap if necessary.
  if (space->GetLiveBitmap() != space->GetMarkBitmap()) {
    CHECK(space->IsContinuousMemMapAllocSpace());
    space->AsContinuousMemMapAllocSpace()->BindLiveToMarkBitmap();
  }
  spaces_.insert(space);
  CreateLargestImmuneRegion();
}

bool ImmuneSpaces::CompareByBegin::operator()(space::ContinuousSpace* a, space::ContinuousSpace* b)
    const {
  return a->Begin() < b->Begin();
}

bool ImmuneSpaces::ContainsSpace(space::ContinuousSpace* space) const {
  return spaces_.find(space) != spaces_.end();
}

}  // namespace collector
}  // namespace gc
}  // namespace art
