/*
 * Copyright (C) 2010 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 "card_table.h"

#include <sys/mman.h>

#include "base/mem_map.h"
#include "base/systrace.h"
#include "base/utils.h"
#include "card_table-inl.h"
#include "gc/heap.h"
#include "gc/space/space.h"
#include "heap_bitmap.h"
#include "runtime.h"

namespace art {
namespace gc {
namespace accounting {

constexpr size_t CardTable::kCardShift;
constexpr size_t CardTable::kCardSize;
constexpr uint8_t CardTable::kCardClean;
constexpr uint8_t CardTable::kCardDirty;

/*
 * Maintain a card table from the write barrier. All writes of
 * non-null values to heap addresses should go through an entry in
 * WriteBarrier, and from there to here.
 *
 * The heap is divided into "cards" of `kCardSize` bytes, as
 * determined by `kCardShift`. The card table contains one byte of
 * data per card, to be used by the GC. The value of the byte will be
 * one of `kCardClean` or `kCardDirty`.
 *
 * After any store of a non-null object pointer into a heap object,
 * code is obliged to mark the card dirty. The setters in
 * object.h [such as SetFieldObject] do this for you. The
 * compiler also contains code to mark cards as dirty.
 *
 * The card table's base [the "biased card table"] gets set to a
 * rather strange value.  In order to keep the JIT from having to
 * fabricate or load `kCardDirty` to store into the card table,
 * biased base is within the mmap allocation at a point where its low
 * byte is equal to `kCardDirty`. See CardTable::Create for details.
 */

CardTable* CardTable::Create(const uint8_t* heap_begin, size_t heap_capacity) {
  ScopedTrace trace(__PRETTY_FUNCTION__);
  /* Set up the card table */
  size_t capacity = heap_capacity / kCardSize;
  /* Allocate an extra 256 bytes to allow fixed low-byte of base */
  std::string error_msg;
  MemMap mem_map = MemMap::MapAnonymous("card table",
                                        /* addr */ nullptr,
                                        capacity + 256,
                                        PROT_READ | PROT_WRITE,
                                        /* low_4gb */ false,
                                        &error_msg);
  CHECK(mem_map.IsValid()) << "couldn't allocate card table: " << error_msg;
  // All zeros is the correct initial value; all clean. Anonymous mmaps are initialized to zero, we
  // don't clear the card table to avoid unnecessary pages being allocated
  static_assert(kCardClean == 0, "kCardClean must be 0");

  uint8_t* cardtable_begin = mem_map.Begin();
  CHECK(cardtable_begin != nullptr);

  // We allocated up to a bytes worth of extra space to allow `biased_begin`'s byte value to equal
  // `kCardDirty`, compute a offset value to make this the case
  size_t offset = 0;
  uint8_t* biased_begin = reinterpret_cast<uint8_t*>(reinterpret_cast<uintptr_t>(cardtable_begin) -
      (reinterpret_cast<uintptr_t>(heap_begin) >> kCardShift));
  uintptr_t biased_byte = reinterpret_cast<uintptr_t>(biased_begin) & 0xff;
  if (biased_byte != kCardDirty) {
    int delta = kCardDirty - biased_byte;
    offset = delta + (delta < 0 ? 0x100 : 0);
    biased_begin += offset;
  }
  CHECK_EQ(reinterpret_cast<uintptr_t>(biased_begin) & 0xff, kCardDirty);
  return new CardTable(std::move(mem_map), biased_begin, offset);
}

CardTable::CardTable(MemMap&& mem_map, uint8_t* biased_begin, size_t offset)
    : mem_map_(std::move(mem_map)), biased_begin_(biased_begin), offset_(offset) {
}

CardTable::~CardTable() {
  // Destroys MemMap via std::unique_ptr<>.
}

void CardTable::ClearCardTable() {
  static_assert(kCardClean == 0, "kCardClean must be 0");
  mem_map_.MadviseDontNeedAndZero();
}

void CardTable::ClearCardRange(uint8_t* start, uint8_t* end) {
  CHECK_ALIGNED(reinterpret_cast<uintptr_t>(start), kCardSize);
  CHECK_ALIGNED(reinterpret_cast<uintptr_t>(end), kCardSize);
  static_assert(kCardClean == 0, "kCardClean must be 0");
  uint8_t* start_card = CardFromAddr(start);
  uint8_t* end_card = CardFromAddr(end);
  ZeroAndReleasePages(start_card, end_card - start_card);
}

bool CardTable::AddrIsInCardTable(const void* addr) const {
  return IsValidCard(biased_begin_ + ((uintptr_t)addr >> kCardShift));
}

void CardTable::CheckAddrIsInCardTable(const uint8_t* addr) const {
  uint8_t* card_addr = biased_begin_ + ((uintptr_t)addr >> kCardShift);
  uint8_t* begin = mem_map_.Begin() + offset_;
  uint8_t* end = mem_map_.End();
  CHECK(AddrIsInCardTable(addr))
      << "Card table " << this
      << " begin: " << reinterpret_cast<void*>(begin)
      << " end: " << reinterpret_cast<void*>(end)
      << " card_addr: " << reinterpret_cast<void*>(card_addr)
      << " heap begin: " << AddrFromCard(begin)
      << " heap end: " << AddrFromCard(end)
      << " addr: " << reinterpret_cast<const void*>(addr);
}

void CardTable::VerifyCardTable() {
  UNIMPLEMENTED(WARNING) << "Card table verification";
}

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