// Copyright 2018 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/isolate-allocator.h"
#include "src/base/bounded-page-allocator.h"
#include "src/isolate.h"
#include "src/ptr-compr.h"
#include "src/utils.h"

namespace v8 {
namespace internal {

IsolateAllocator::IsolateAllocator(IsolateAllocationMode mode) {
#if V8_TARGET_ARCH_64_BIT
  if (mode == IsolateAllocationMode::kInV8Heap) {
    Address heap_reservation_address = InitReservation();
    CommitPagesForIsolate(heap_reservation_address);
    return;
  }
#endif  // V8_TARGET_ARCH_64_BIT

  // Allocate Isolate in C++ heap.
  CHECK_EQ(mode, IsolateAllocationMode::kInCppHeap);
  page_allocator_ = GetPlatformPageAllocator();
  isolate_memory_ = ::operator new(sizeof(Isolate));
  DCHECK(!reservation_.IsReserved());
}

IsolateAllocator::~IsolateAllocator() {
  if (reservation_.IsReserved()) {
    // The actual memory will be freed when the |reservation_| will die.
    return;
  }

  // The memory was allocated in C++ heap.
  ::operator delete(isolate_memory_);
}

#if V8_TARGET_ARCH_64_BIT
Address IsolateAllocator::InitReservation() {
  v8::PageAllocator* platform_page_allocator = GetPlatformPageAllocator();

  // Reserve a 4Gb region so that the middle is 4Gb aligned.
  // The VirtualMemory API does not support such an constraint so we have to
  // implement it manually here.
  size_t reservation_size = kPtrComprHeapReservationSize;
  size_t base_alignment = kPtrComprIsolateRootAlignment;

  const int kMaxAttempts = 3;
  for (int attempt = 0; attempt < kMaxAttempts; ++attempt) {
    Address hint = RoundDown(reinterpret_cast<Address>(
                                 platform_page_allocator->GetRandomMmapAddr()),
                             base_alignment) +
                   kPtrComprIsolateRootBias;

    // Within this reservation there will be a sub-region with proper alignment.
    VirtualMemory padded_reservation(platform_page_allocator,
                                     reservation_size * 2,
                                     reinterpret_cast<void*>(hint));
    if (!padded_reservation.IsReserved()) break;

    // Find such a sub-region inside the reservation that it's middle is
    // |base_alignment|-aligned.
    Address address =
        RoundUp(padded_reservation.address() + kPtrComprIsolateRootBias,
                base_alignment) -
        kPtrComprIsolateRootBias;
    CHECK(padded_reservation.InVM(address, reservation_size));

#if defined(V8_OS_FUCHSIA)
    // Fuchsia does not respect given hints so as a workaround we will use
    // overreserved address space region instead of trying to re-reserve
    // a subregion.
    if (padded_reservation.InVM(address, reservation_size)) {
      reservation_ = std::move(padded_reservation);
      return address;
    }
#else
    // Now free the padded reservation and immediately try to reserve an exact
    // region at aligned address. We have to do this dancing because the
    // reservation address requirement is more complex than just a certain
    // alignment and not all operating systems support freeing parts of reserved
    // address space regions.
    padded_reservation.Free();

    VirtualMemory reservation(platform_page_allocator, reservation_size,
                              reinterpret_cast<void*>(address));
    if (!reservation.IsReserved()) break;

    // The reservation could still be somewhere else but we can accept it
    // if the reservation has the required alignment.
    Address aligned_address =
        RoundUp(reservation.address() + kPtrComprIsolateRootBias,
                base_alignment) -
        kPtrComprIsolateRootBias;

    if (reservation.address() == aligned_address) {
      reservation_ = std::move(reservation);
      CHECK_EQ(reservation_.size(), reservation_size);
      return aligned_address;
    }
#endif
  }
  V8::FatalProcessOutOfMemory(nullptr,
                              "Failed to reserve memory for new V8 Isolate");
  return kNullAddress;
}

void IsolateAllocator::CommitPagesForIsolate(Address heap_address) {
  CHECK(reservation_.InVM(heap_address, kPtrComprHeapReservationSize));

  Address isolate_root = heap_address + kPtrComprIsolateRootBias;
  CHECK(IsAligned(isolate_root, kPtrComprIsolateRootAlignment));

  v8::PageAllocator* platform_page_allocator = GetPlatformPageAllocator();

  // Simplify BoundedPageAllocator's life by configuring it to use same page
  // size as the Heap will use (MemoryChunk::kPageSize).
  size_t page_size = RoundUp(size_t{1} << kPageSizeBits,
                             platform_page_allocator->AllocatePageSize());

  page_allocator_instance_ = base::make_unique<base::BoundedPageAllocator>(
      platform_page_allocator, heap_address, kPtrComprHeapReservationSize,
      page_size);
  page_allocator_ = page_allocator_instance_.get();

  Address isolate_address = isolate_root - Isolate::isolate_root_bias();
  Address isolate_end = isolate_address + sizeof(Isolate);

  // Inform the bounded page allocator about reserved pages.
  {
    Address reserved_region_address = RoundDown(isolate_address, page_size);
    size_t reserved_region_size =
        RoundUp(isolate_end, page_size) - reserved_region_address;

    CHECK(page_allocator_instance_->AllocatePagesAt(
        reserved_region_address, reserved_region_size,
        PageAllocator::Permission::kNoAccess));
  }

  // Commit pages where the Isolate will be stored.
  {
    size_t commit_page_size = platform_page_allocator->CommitPageSize();
    Address committed_region_address =
        RoundDown(isolate_address, commit_page_size);
    size_t committed_region_size =
        RoundUp(isolate_end, commit_page_size) - committed_region_address;

    // We are using |reservation_| directly here because |page_allocator_| has
    // bigger commit page size than we actually need.
    CHECK(reservation_.SetPermissions(committed_region_address,
                                      committed_region_size,
                                      PageAllocator::kReadWrite));

    if (Heap::ShouldZapGarbage()) {
      for (Address address = committed_region_address;
           address < committed_region_size; address += kSystemPointerSize) {
        Memory<Address>(address) = static_cast<Address>(kZapValue);
      }
    }
  }
  isolate_memory_ = reinterpret_cast<void*>(isolate_address);
}
#endif  // V8_TARGET_ARCH_64_BIT

}  // namespace internal
}  // namespace v8
