/*
 * 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 "bitmap-inl.h"

#include <sys/mman.h>  // For the PROT_* and MAP_* constants.

#include "base/bit_utils.h"
#include "base/mem_map.h"
#include "card_table.h"
#include "gc/collector/mark_compact.h"
#include "jit/jit_memory_region.h"

namespace art HIDDEN {
namespace gc {
namespace accounting {

Bitmap* Bitmap::CreateFromMemMap(MemMap&& mem_map, size_t num_bits) {
  CHECK(mem_map.IsValid());
  return new Bitmap(std::move(mem_map), num_bits);
}

Bitmap::Bitmap(MemMap&& mem_map, size_t num_bits)
    : mem_map_(std::move(mem_map)),
      bitmap_begin_(reinterpret_cast<uintptr_t*>(mem_map_.Begin())),
      bitmap_numbits_(num_bits) {
  CHECK(bitmap_begin_ != nullptr);
  CHECK_NE(num_bits, 0U);
}

Bitmap::~Bitmap() {
  // Destroys member MemMap.
}

MemMap Bitmap::AllocateMemMap(const std::string& name, size_t num_bits) {
  const size_t bitmap_size = RoundUp(
      RoundUp(num_bits, kBitsPerBitmapWord) / kBitsPerBitmapWord * sizeof(uintptr_t), gPageSize);
  std::string error_msg;
  MemMap mem_map = MemMap::MapAnonymous(name.c_str(),
                                        bitmap_size,
                                        PROT_READ | PROT_WRITE,
                                        /*low_4gb=*/ false,
                                        &error_msg);
  if (UNLIKELY(!mem_map.IsValid())) {
    LOG(ERROR) << "Failed to allocate bitmap " << name << ": " << error_msg;
  }
  return mem_map;
}

Bitmap* Bitmap::Create(const std::string& name, size_t num_bits) {
  MemMap mem_map = AllocateMemMap(name, num_bits);
  if (UNLIKELY(!mem_map.IsValid())) {
    return nullptr;
  }
  return CreateFromMemMap(std::move(mem_map), num_bits);
}

void Bitmap::Clear() {
  if (bitmap_begin_ != nullptr) {
    mem_map_.MadviseDontNeedAndZero();
  }
}

void Bitmap::CopyFrom(Bitmap* source_bitmap) {
  DCHECK_EQ(BitmapSize(), source_bitmap->BitmapSize());
  std::copy(source_bitmap->Begin(),
            source_bitmap->Begin() + BitmapSize() / kBitsPerBitmapWord, Begin());
}

template<size_t kAlignment>
MemoryRangeBitmap<kAlignment>* MemoryRangeBitmap<kAlignment>::Create(
    const std::string& name, uintptr_t cover_begin, uintptr_t cover_end) {
  CHECK_ALIGNED(cover_begin, kAlignment);
  CHECK_ALIGNED(cover_end, kAlignment);
  const size_t num_bits = (cover_end - cover_begin) / kAlignment;
  MemMap mem_map = Bitmap::AllocateMemMap(name, num_bits);
  CHECK(mem_map.IsValid());
  return CreateFromMemMap(std::move(mem_map), cover_begin, num_bits);
}

template<size_t kAlignment>
MemoryRangeBitmap<kAlignment>* MemoryRangeBitmap<kAlignment>::CreateFromMemMap(
    MemMap&& mem_map, uintptr_t begin, size_t num_bits) {
  return new MemoryRangeBitmap(std::move(mem_map), begin, num_bits);
}

template class MemoryRangeBitmap<CardTable::kCardSize>;
template class MemoryRangeBitmap<jit::kJitCodeAccountingBytes>;
template class MemoryRangeBitmap<collector::MarkCompact::kAlignment>;

}  // namespace accounting
}  // namespace gc
}  // namespace art

