// 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/init/isolate-allocator.h"
#include "src/base/bounded-page-allocator.h"
#include "src/common/ptr-compr.h"
#include "src/execution/isolate.h"
#include "src/utils/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) {
        base::Memory<Address>(address) = static_cast<Address>(kZapValue);
      }
    }
  }
  isolate_memory_ = reinterpret_cast<void*>(isolate_address);
}
#endif  // V8_TARGET_ARCH_64_BIT

}  // namespace internal
}  // namespace v8
