// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#include "vm/virtual_memory_compressed.h"

#include "platform/utils.h"

#if defined(DART_COMPRESSED_HEAP)

namespace dart {

uword VirtualMemoryCompressedHeap::base_ = 0;
uword VirtualMemoryCompressedHeap::size_ = 0;
uint8_t* VirtualMemoryCompressedHeap::pages_ = nullptr;
uword VirtualMemoryCompressedHeap::minimum_free_page_id_ = 0;
Mutex* VirtualMemoryCompressedHeap::mutex_ = nullptr;

uint8_t PageMask(uword page_id) {
  return static_cast<uint8_t>(1 << (page_id % 8));
}

bool VirtualMemoryCompressedHeap::IsPageUsed(uword page_id) {
  if (page_id >= kCompressedHeapNumPages) return false;
  return pages_[page_id / 8] & PageMask(page_id);
}

void VirtualMemoryCompressedHeap::SetPageUsed(uword page_id) {
  ASSERT(page_id < kCompressedHeapNumPages);
  pages_[page_id / 8] |= PageMask(page_id);
}

void VirtualMemoryCompressedHeap::ClearPageUsed(uword page_id) {
  ASSERT(page_id < kCompressedHeapNumPages);
  pages_[page_id / 8] &= ~PageMask(page_id);
}

void VirtualMemoryCompressedHeap::Init(void* compressed_heap_region,
                                       size_t size) {
  pages_ = new uint8_t[kCompressedHeapBitmapSize];
  memset(pages_, 0, kCompressedHeapBitmapSize);
  ASSERT(size > 0);
  ASSERT(size <= kCompressedHeapSize);
  for (intptr_t page_id = size / kCompressedHeapPageSize;
       page_id < kCompressedHeapNumPages; page_id++) {
    SetPageUsed(page_id);
  }
  base_ = reinterpret_cast<uword>(compressed_heap_region);
  size_ = size;
  ASSERT(base_ != 0);
  ASSERT(size_ != 0);
  ASSERT(size_ <= kCompressedHeapSize);
  ASSERT(Utils::IsAligned(base_, kCompressedHeapPageSize));
  ASSERT(Utils::IsAligned(size_, kCompressedHeapPageSize));
  // base_ is not necessarily 4GB-aligned, because on some systems we can't make
  // a large enough reservation to guarentee it. Instead, we have only the
  // weaker property that all addresses in [base_, base_ + size_) have the same
  // same upper 32 bits, which is what we really need for compressed pointers.
  intptr_t mask = ~(kCompressedHeapAlignment - 1);
  ASSERT((base_ & mask) == (base_ + size_ - 1 & mask));
  mutex_ = new Mutex(NOT_IN_PRODUCT("compressed_heap_mutex"));
}

void VirtualMemoryCompressedHeap::Cleanup() {
  delete[] pages_;
  delete mutex_;
  base_ = 0;
  size_ = 0;
  pages_ = nullptr;
  minimum_free_page_id_ = 0;
  mutex_ = nullptr;
}

void* VirtualMemoryCompressedHeap::GetRegion() {
  return reinterpret_cast<void*>(base_);
}

MemoryRegion VirtualMemoryCompressedHeap::Allocate(intptr_t size,
                                                   intptr_t alignment) {
  ASSERT(alignment <= kCompressedHeapAlignment);
  const intptr_t allocated_size = Utils::RoundUp(size, kCompressedHeapPageSize);
  uword pages = allocated_size / kCompressedHeapPageSize;
  uword page_alignment = alignment > kCompressedHeapPageSize
                             ? alignment / kCompressedHeapPageSize
                             : 1;
  MutexLocker ml(mutex_);

  // Find a gap with enough empty pages, using the bitmap. Note that reading
  // outside the bitmap range always returns 0, so this loop will terminate.
  uword page_id = Utils::RoundUp(minimum_free_page_id_, page_alignment);
  for (uword gap = 0;;) {
    if (IsPageUsed(page_id)) {
      gap = 0;
      page_id = Utils::RoundUp(page_id + 1, page_alignment);
    } else {
      ++gap;
      if (gap >= pages) {
        page_id += 1 - gap;
        break;
      }
      ++page_id;
    }
  }
  ASSERT(page_id % page_alignment == 0);

  // Make sure we're not trying to allocate past the end of the heap.
  uword end = page_id + pages;
  if (end > kCompressedHeapSize / kCompressedHeapPageSize) {
    return MemoryRegion();
  }

  // Mark all the pages in the bitmap as allocated.
  for (uword i = page_id; i < end; ++i) {
    ASSERT(!IsPageUsed(i));
    SetPageUsed(i);
  }

  // Find the next free page, to speed up subsequent allocations.
  while (IsPageUsed(minimum_free_page_id_)) {
    ++minimum_free_page_id_;
  }

  uword address = base_ + page_id * kCompressedHeapPageSize;
  ASSERT(Utils::IsAligned(address, kCompressedHeapPageSize));
  return MemoryRegion(reinterpret_cast<void*>(address), allocated_size);
}

void VirtualMemoryCompressedHeap::Free(void* address, intptr_t size) {
  uword start = reinterpret_cast<uword>(address);
  ASSERT(Utils::IsAligned(start, kCompressedHeapPageSize));
  ASSERT(Utils::IsAligned(size, kCompressedHeapPageSize));
  MutexLocker ml(mutex_);
  ASSERT(start >= base_);
  uword page_id = (start - base_) / kCompressedHeapPageSize;
  uword end = page_id + size / kCompressedHeapPageSize;
  for (uword i = page_id; i < end; ++i) {
    ClearPageUsed(i);
  }
  if (page_id < minimum_free_page_id_) {
    minimum_free_page_id_ = page_id;
  }
}

bool VirtualMemoryCompressedHeap::Contains(void* address) {
  return (reinterpret_cast<uword>(address) - base_) < size_;
}

}  // namespace dart

#endif  // defined(DART_COMPRESSED_HEAP)
