/*
 * 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>  /* for PROT_* */

#include "heap.h"
#include "heap_bitmap.h"
#include "logging.h"
#include "runtime.h"
#include "space.h"
#include "utils.h"

namespace art {
/*
 * 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 GC_CARD_SIZE bytes, as
 * determined by GC_CARD_SHIFT. 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 GC_CARD_CLEAN or GC_CARD_DIRTY.
 *
 * 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 GC_DIRTY_CARD to store into the card table,
 * biased base is within the mmap allocation at a point where its low
 * byte is equal to GC_DIRTY_CARD. See CardTable::Create for details.
 */

CardTable* CardTable::Create(const byte* heap_begin, size_t heap_capacity) {
  /* Set up the card table */
  size_t capacity = heap_capacity / GC_CARD_SIZE;
  /* Allocate an extra 256 bytes to allow fixed low-byte of base */
  UniquePtr<MemMap> mem_map(MemMap::MapAnonymous("dalvik-card-table", NULL,
                                                 capacity + 256, PROT_READ | PROT_WRITE));
  if (mem_map.get() == NULL) {
    std::string maps;
    ReadFileToString("/proc/self/maps", &maps);
    LOG(FATAL) << "couldn't allocate card table\n" << maps;
  }
  // 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
  CHECK_EQ(GC_CARD_CLEAN, 0);

  byte* cardtable_begin = mem_map->Begin();
  CHECK(cardtable_begin != NULL);

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

  return new CardTable(mem_map.release(), biased_begin, offset);
}

void CardTable::ClearNonImageSpaceCards(Heap* heap) {
  // TODO: clear just the range of the table that has been modified
  const std::vector<Space*>& spaces = heap->GetSpaces();
  for (size_t i = 0; i < spaces.size(); ++i) {
    if (!spaces[i]->IsImageSpace()) {
      byte* card_start = CardFromAddr(spaces[i]->Begin());
      byte* card_end = CardFromAddr(spaces[i]->End());
      memset(reinterpret_cast<void*>(card_start), GC_CARD_CLEAN, card_end - card_start);
    }
  }
}

void CardTable::ClearCardTable() {
  // TODO: clear just the range of the table that has been modified
  memset(mem_map_->Begin(), GC_CARD_CLEAN, mem_map_->Size());
}

void CardTable::CheckAddrIsInCardTable(const byte* addr) const {
  byte* cardAddr = biased_begin_ + ((uintptr_t)addr >> GC_CARD_SHIFT);
  if (!IsValidCard(cardAddr)) {
    byte* begin = mem_map_->Begin() + offset_;
    byte* end = mem_map_->End();
    LOG(FATAL) << "Cardtable - begin: " << reinterpret_cast<void*>(begin)
               << " end: " << reinterpret_cast<void*>(end)
               << " addr: " << reinterpret_cast<const void*>(addr)
               << " cardAddr: " << reinterpret_cast<void*>(cardAddr);
  }
}

void CardTable::Scan(HeapBitmap* bitmap, byte* heap_begin, byte* heap_end, Callback* visitor, void* arg) const {
  byte* card_cur = CardFromAddr(heap_begin);
  byte* card_end = CardFromAddr(heap_end);
  while (card_cur < card_end) {
    while (card_cur < card_end && *card_cur == GC_CARD_CLEAN) {
      card_cur++;
    }
    byte* run_start = card_cur;
    size_t run = 0;
    while (card_cur < card_end && *card_cur == GC_CARD_DIRTY) {
      run++;
      card_cur++;
    }
    if (run > 0) {
      byte* run_end = &card_cur[run];
      bitmap->VisitRange(reinterpret_cast<uintptr_t>(AddrFromCard(run_start)),
                                      reinterpret_cast<uintptr_t>(AddrFromCard(run_end)),
                                      visitor, arg);
    }
  }
}

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

}  // namespace art
