// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/heap/cppgc/gc-info-table.h"

#include <algorithm>
#include <limits>
#include <memory>

#include "include/cppgc/internal/gc-info.h"
#include "include/cppgc/platform.h"
#include "src/base/bits.h"
#include "src/base/lazy-instance.h"

namespace cppgc {
namespace internal {

namespace {

// GCInfoTable::table_, the table which holds GCInfos, is maintained as a
// contiguous array reserved upfront. Subparts of the array are (re-)committed
// as read/write or read-only in OS pages, whose size is a power of 2. To avoid
// having GCInfos that cross the boundaries between these subparts we force the
// size of GCInfo to be a power of 2 as well.
constexpr size_t kEntrySize = sizeof(GCInfo);
static_assert(v8::base::bits::IsPowerOfTwo(kEntrySize),
              "GCInfoTable entries size must be power of "
              "two");

}  // namespace

GCInfoTable* GlobalGCInfoTable::global_table_ = nullptr;
constexpr GCInfoIndex GCInfoTable::kMaxIndex;
constexpr GCInfoIndex GCInfoTable::kMinIndex;
constexpr GCInfoIndex GCInfoTable::kInitialWantedLimit;

void GlobalGCInfoTable::Create(PageAllocator* page_allocator) {
  static v8::base::LeakyObject<GCInfoTable> table(page_allocator);
  if (!global_table_) {
    global_table_ = table.get();
  }
}

GCInfoTable::GCInfoTable(PageAllocator* page_allocator)
    : page_allocator_(page_allocator),
      table_(static_cast<decltype(table_)>(page_allocator_->AllocatePages(
          nullptr, MaxTableSize(), page_allocator_->AllocatePageSize(),
          PageAllocator::kNoAccess))),
      read_only_table_end_(reinterpret_cast<uint8_t*>(table_)) {
  CHECK(table_);
  Resize();
}

GCInfoTable::~GCInfoTable() {
  page_allocator_->ReleasePages(const_cast<GCInfo*>(table_), MaxTableSize(), 0);
}

size_t GCInfoTable::MaxTableSize() const {
  return RoundUp(GCInfoTable::kMaxIndex * kEntrySize,
                 page_allocator_->AllocatePageSize());
}

GCInfoIndex GCInfoTable::InitialTableLimit() const {
  // Different OSes have different page sizes, so we have to choose the minimum
  // of memory wanted and OS page size.
  constexpr size_t memory_wanted = kInitialWantedLimit * kEntrySize;
  const size_t initial_limit =
      RoundUp(memory_wanted, page_allocator_->AllocatePageSize()) / kEntrySize;
  CHECK_GT(std::numeric_limits<GCInfoIndex>::max(), initial_limit);
  return static_cast<GCInfoIndex>(
      std::min(static_cast<size_t>(kMaxIndex), initial_limit));
}

void GCInfoTable::Resize() {
  const GCInfoIndex new_limit = (limit_) ? 2 * limit_ : InitialTableLimit();
  CHECK_GT(new_limit, limit_);
  const size_t old_committed_size = limit_ * kEntrySize;
  const size_t new_committed_size = new_limit * kEntrySize;
  CHECK(table_);
  CHECK_EQ(0u, new_committed_size % page_allocator_->AllocatePageSize());
  CHECK_GE(MaxTableSize(), new_committed_size);
  // Recommit new area as read/write.
  uint8_t* current_table_end =
      reinterpret_cast<uint8_t*>(table_) + old_committed_size;
  const size_t table_size_delta = new_committed_size - old_committed_size;
  CHECK(page_allocator_->SetPermissions(current_table_end, table_size_delta,
                                        PageAllocator::kReadWrite));
  // Recommit old area as read-only.
  if (read_only_table_end_ != current_table_end) {
    DCHECK_GT(current_table_end, read_only_table_end_);
    const size_t read_only_delta = current_table_end - read_only_table_end_;
    CHECK(page_allocator_->SetPermissions(read_only_table_end_, read_only_delta,
                                          PageAllocator::kRead));
    read_only_table_end_ += read_only_delta;
  }

  // Check that newly-committed memory is zero-initialized.
  CheckMemoryIsZeroed(reinterpret_cast<uintptr_t*>(current_table_end),
                      table_size_delta / sizeof(uintptr_t));

  limit_ = new_limit;
}

void GCInfoTable::CheckMemoryIsZeroed(uintptr_t* base, size_t len) {
#if DEBUG
  for (size_t i = 0; i < len; ++i) {
    DCHECK(!base[i]);
  }
#endif  // DEBUG
}

GCInfoIndex GCInfoTable::RegisterNewGCInfo(const GCInfo& info) {
  // Ensuring a new index involves current index adjustment as well as
  // potentially resizing the table. For simplicity we use a lock.
  v8::base::MutexGuard guard(&table_mutex_);

  if (current_index_ == limit_) {
    Resize();
  }

  GCInfoIndex new_index = current_index_++;
  CHECK_LT(new_index, GCInfoTable::kMaxIndex);
  table_[new_index] = info;
  return new_index;
}

}  // namespace internal
}  // namespace cppgc
