/*
 * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 *
 */

#include "jvm.h"
#include "logging/log.hpp"
#include "memory/memoryReserver.hpp"
#include "oops/compressedOops.hpp"
#include "oops/markWord.hpp"
#include "runtime/globals_extension.hpp"
#include "runtime/java.hpp"
#include "runtime/os.inline.hpp"
#include "utilities/formatBuffer.hpp"
#include "utilities/globalDefinitions.hpp"
#include "utilities/powerOfTwo.hpp"

static void sanity_check_size_and_alignment(size_t size, size_t alignment) {
  assert(size > 0, "Precondition");

  DEBUG_ONLY(const size_t granularity = os::vm_allocation_granularity());
  assert(is_aligned(size, granularity), "size not aligned to os::vm_allocation_granularity()");

  assert(alignment >= granularity, "Must be set");
  assert(is_power_of_2(alignment), "not a power of 2");
  assert(is_aligned(alignment, granularity), "alignment not aligned to os::vm_allocation_granularity()");
}

static void sanity_check_page_size(size_t page_size) {
  assert(page_size >= os::vm_page_size(), "Invalid page size");
  assert(is_power_of_2(page_size), "Invalid page size");
}

static void sanity_check_arguments(size_t size, size_t alignment, size_t page_size) {
  sanity_check_size_and_alignment(size, alignment);
  sanity_check_page_size(page_size);
}

static bool large_pages_requested() {
  return UseLargePages &&
         (!FLAG_IS_DEFAULT(UseLargePages) || !FLAG_IS_DEFAULT(LargePageSizeInBytes));
}

static void log_on_large_pages_failure(char* req_addr, size_t bytes) {
  if (large_pages_requested()) {
    // Compressed oops logging.
    log_debug(gc, heap, coops)("Reserve regular memory without large pages");
    // JVM style warning that we did not succeed in using large pages.
    char msg[128];
    jio_snprintf(msg, sizeof(msg), "Failed to reserve and commit memory using large pages. "
                                   "req_addr: " PTR_FORMAT " bytes: %zu",
                                   req_addr, bytes);
    warning("%s", msg);
  }
}

static bool use_explicit_large_pages(size_t page_size) {
  return !os::can_commit_large_page_memory() &&
         page_size != os::vm_page_size();
}

static char* reserve_memory_inner(char* requested_address,
                                  size_t size,
                                  size_t alignment,
                                  bool exec,
                                  MemTag mem_tag) {
  // If the memory was requested at a particular address, use
  // os::attempt_reserve_memory_at() to avoid mapping over something
  // important.  If the reservation fails, return null.
  if (requested_address != nullptr) {
    assert(is_aligned(requested_address, alignment),
           "Requested address " PTR_FORMAT " must be aligned to %zu",
           p2i(requested_address), alignment);
    return os::attempt_reserve_memory_at(requested_address, size, mem_tag, exec);
  }

  // Optimistically assume that the OS returns an aligned base pointer.
  // When reserving a large address range, most OSes seem to align to at
  // least 64K.
  char* base = os::reserve_memory(size, mem_tag, exec);
  if (is_aligned(base, alignment)) {
    return base;
  }

  // Base not aligned, retry.
  if (!os::release_memory(base, size)) {
    fatal("os::release_memory failed");
  }

  // Map using the requested alignment.
  return os::reserve_memory_aligned(size, alignment, mem_tag, exec);
}

ReservedSpace MemoryReserver::reserve_memory(char* requested_address,
                                             size_t size,
                                             size_t alignment,
                                             size_t page_size,
                                             bool exec,
                                             MemTag mem_tag) {
  char* base = reserve_memory_inner(requested_address, size, alignment, exec, mem_tag);

  if (base != nullptr) {
    return ReservedSpace(base, size, alignment, page_size, exec, false /* special */);
  }

  // Failed
  return {};
}

ReservedSpace MemoryReserver::reserve_memory_special(char* requested_address,
                                                     size_t size,
                                                     size_t alignment,
                                                     size_t page_size,
                                                     bool exec) {
  log_trace(pagesize)("Attempt special mapping: size: " EXACTFMT ", alignment: " EXACTFMT,
                      EXACTFMTARGS(size),
                      EXACTFMTARGS(alignment));

  char* base = os::reserve_memory_special(size, alignment, page_size, requested_address, exec);

  if (base != nullptr) {
    assert(is_aligned(base, alignment),
           "reserve_memory_special() returned an unaligned address, "
           "base: " PTR_FORMAT " alignment: 0x%zx",
           p2i(base), alignment);

    return ReservedSpace(base, size, alignment, page_size, exec, true /* special */);
  }

  // Failed
  return {};
}

ReservedSpace MemoryReserver::reserve(char* requested_address,
                                      size_t size,
                                      size_t alignment,
                                      size_t page_size,
                                      bool executable,
                                      MemTag mem_tag) {
  sanity_check_arguments(size, alignment, page_size);

  // Reserve the memory.

  // There are basically three different cases that we need to handle:
  // 1. Mapping backed by a file
  // 2. Mapping backed by explicit large pages
  // 3. Mapping backed by normal pages or transparent huge pages
  // The first two have restrictions that requires the whole mapping to be
  // committed up front. To record this the ReservedSpace is marked 'special'.

  // == Case 1 ==
  // This case is contained within the HeapReserver

  // == Case 2 ==
  if (use_explicit_large_pages(page_size)) {
    // System can't commit large pages i.e. use transparent huge pages and
    // the caller requested large pages. To satisfy this request we use
    // explicit large pages and these have to be committed up front to ensure
    // no reservations are lost.
    do {
      ReservedSpace reserved = reserve_memory_special(requested_address, size, alignment, page_size, executable);
      if (reserved.is_reserved()) {
        // Successful reservation using large pages.
        return reserved;
      }
      page_size = os::page_sizes().next_smaller(page_size);
    } while (page_size > os::vm_page_size());

    // Failed to reserve explicit large pages, do proper logging.
    log_on_large_pages_failure(requested_address, size);
    // Now fall back to normal reservation.
    assert(page_size == os::vm_page_size(), "inv");
  }

  // == Case 3 ==
  return reserve_memory(requested_address, size, alignment, page_size, executable, mem_tag);
}

ReservedSpace MemoryReserver::reserve(char* requested_address,
                                      size_t size,
                                      size_t alignment,
                                      size_t page_size,
                                      MemTag mem_tag) {
  return reserve(requested_address,
                 size,
                 alignment,
                 page_size,
                 !ExecMem,
                 mem_tag);
}


ReservedSpace MemoryReserver::reserve(size_t size,
                                      size_t alignment,
                                      size_t page_size,
                                      MemTag mem_tag) {
  return reserve(nullptr /* requested_address */,
                 size,
                 alignment,
                 page_size,
                 mem_tag);
}

ReservedSpace MemoryReserver::reserve(size_t size,
                                      MemTag mem_tag) {
  // Want to use large pages where possible. If the size is
  // not large page aligned the mapping will be a mix of
  // large and normal pages.
  size_t page_size = os::page_size_for_region_unaligned(size, 1);
  size_t alignment = os::vm_allocation_granularity();

  return reserve(size,
                 alignment,
                 page_size,
                 mem_tag);
}

bool MemoryReserver::release(const ReservedSpace& reserved) {
  assert(reserved.is_reserved(), "Precondition");

  if (reserved.special()) {
    return os::release_memory_special(reserved.base(), reserved.size());
  } else {
    return os::release_memory(reserved.base(), reserved.size());
  }
}

static char* map_memory_to_file(char* requested_address,
                                size_t size,
                                size_t alignment,
                                int fd,
                                MemTag mem_tag) {
  // If the memory was requested at a particular address, use
  // os::attempt_reserve_memory_at() to avoid mapping over something
  // important.  If the reservation fails, return null.
  if (requested_address != nullptr) {
    assert(is_aligned(requested_address, alignment),
           "Requested address " PTR_FORMAT " must be aligned to %zu",
           p2i(requested_address), alignment);
    return os::attempt_map_memory_to_file_at(requested_address, size, fd, mem_tag);
  }

  // Optimistically assume that the OS returns an aligned base pointer.
  // When reserving a large address range, most OSes seem to align to at
  // least 64K.
  char* base = os::map_memory_to_file(size, fd, mem_tag);
  if (is_aligned(base, alignment)) {
    return base;
  }


  // Base not aligned, retry.
  if (!os::unmap_memory(base, size)) {
    fatal("os::unmap_memory failed");
  }

  // Map using the requested alignment.
  return os::map_memory_to_file_aligned(size, alignment, fd, mem_tag);
}

ReservedSpace FileMappedMemoryReserver::reserve(char* requested_address,
                                                size_t size,
                                                size_t alignment,
                                                int fd,
                                                MemTag mem_tag) {
  sanity_check_size_and_alignment(size, alignment);

  char* base = map_memory_to_file(requested_address, size, alignment, fd, mem_tag);

  if (base != nullptr) {
    return ReservedSpace(base, size, alignment, os::vm_page_size(), !ExecMem, true /* special */);
  }

  // Failed
  return {};
}

ReservedSpace CodeMemoryReserver::reserve(size_t size,
                                          size_t alignment,
                                          size_t page_size) {
  return MemoryReserver::reserve(nullptr /* requested_address */,
                                 size,
                                 alignment,
                                 page_size,
                                 ExecMem,
                                 mtCode);
}

ReservedHeapSpace HeapReserver::Instance::reserve_uncompressed_oops_heap(size_t size,
                                                                         size_t alignment,
                                                                         size_t page_size) {
  ReservedSpace reserved = reserve_memory(size, alignment, page_size);

  if (reserved.is_reserved()) {
    return ReservedHeapSpace(reserved, 0 /* noaccess_prefix */);
  }

  // Failed
  return {};
}


static int maybe_create_file(const char* heap_allocation_directory) {
  if (heap_allocation_directory == nullptr) {
    return -1;
  }

  int fd = os::create_file_for_heap(heap_allocation_directory);
  if (fd == -1) {
    vm_exit_during_initialization(
        err_msg("Could not create file for Heap at location %s", heap_allocation_directory));
  }

  return fd;
}

HeapReserver::Instance::Instance(const char* heap_allocation_directory)
  : _fd(maybe_create_file(heap_allocation_directory)) {}

HeapReserver::Instance::~Instance() {
  if (_fd != -1) {
    ::close(_fd);
  }
}

ReservedSpace HeapReserver::Instance::reserve_memory(size_t size,
                                                     size_t alignment,
                                                     size_t page_size,
                                                     char* requested_address) {

  // There are basically three different cases that we need to handle below:
  // 1. Mapping backed by a file
  // 2. Mapping backed by explicit large pages
  // 3. Mapping backed by normal pages or transparent huge pages
  // The first two have restrictions that requires the whole mapping to be
  // committed up front. To record this the ReservedSpace is marked 'special'.

  // == Case 1 ==
  if (_fd != -1) {
    // When there is a backing file directory for this space then whether
    // large pages are allocated is up to the filesystem of the backing file.
    // So UseLargePages is not taken into account for this reservation.
    //
    // If requested, let the user know that explicit large pages can't be used.
    if (use_explicit_large_pages(page_size) && large_pages_requested()) {
      log_debug(gc, heap)("Cannot allocate explicit large pages for Java Heap when AllocateHeapAt option is set.");
    }

    // Always return, not possible to fall back to reservation not using a file.
    return FileMappedMemoryReserver::reserve(requested_address, size, alignment, _fd, mtJavaHeap);
  }

  // == Case 2 & 3 ==
  return MemoryReserver::reserve(requested_address, size, alignment, page_size, mtJavaHeap);
}

// Compressed oop support is not relevant in 32bit builds.
#ifdef _LP64

void HeapReserver::Instance::release(const ReservedSpace& reserved) {
  if (reserved.is_reserved()) {
    if (_fd == -1) {
      if (reserved.special()) {
        os::release_memory_special(reserved.base(), reserved.size());
      } else{
        os::release_memory(reserved.base(), reserved.size());
      }
    } else {
      os::unmap_memory(reserved.base(), reserved.size());
    }
  }
}

// Tries to allocate memory of size 'size' at address requested_address with alignment 'alignment'.
// Does not check whether the reserved memory actually is at requested_address, as the memory returned
// might still fulfill the wishes of the caller.
// Assures the memory is aligned to 'alignment'.
ReservedSpace HeapReserver::Instance::try_reserve_memory(size_t size,
                                                         size_t alignment,
                                                         size_t page_size,
                                                         char* requested_address) {
  // Try to reserve the memory for the heap.
  log_trace(gc, heap, coops)("Trying to allocate at address " PTR_FORMAT
                             " heap of size 0x%zx",
                             p2i(requested_address),
                             size);

  ReservedSpace reserved = reserve_memory(size, alignment, page_size, requested_address);

  if (reserved.is_reserved()) {
    // Check alignment constraints.
    assert(reserved.alignment() == alignment, "Unexpected");
    assert(is_aligned(reserved.base(), alignment), "Unexpected");
    return reserved;
  }

  // Failed
  return {};
}

ReservedSpace HeapReserver::Instance::try_reserve_range(char *highest_start,
                                                        char *lowest_start,
                                                        size_t attach_point_alignment,
                                                        char *aligned_heap_base_min_address,
                                                        char *upper_bound,
                                                        size_t size,
                                                        size_t alignment,
                                                        size_t page_size) {
  assert(is_aligned(highest_start, attach_point_alignment), "precondition");
  assert(is_aligned(lowest_start, attach_point_alignment), "precondition");

  const size_t attach_range = pointer_delta(highest_start, lowest_start, sizeof(char));
  const size_t num_attempts_possible = (attach_range / attach_point_alignment) + 1;
  const size_t num_attempts_to_try   = MIN2((size_t)HeapSearchSteps, num_attempts_possible);
  const size_t num_intervals = num_attempts_to_try - 1;
  const size_t stepsize = num_intervals == 0 ? 0 : align_down(attach_range / num_intervals, attach_point_alignment);

  for (size_t i = 0; i < num_attempts_to_try; ++i) {
    char* const attach_point = highest_start - stepsize * i;
    ReservedSpace reserved = try_reserve_memory(size, alignment, page_size, attach_point);

    if (reserved.is_reserved()) {
      if (reserved.base() >= aligned_heap_base_min_address &&
          size <= (uintptr_t)(upper_bound - reserved.base())) {
        // Got a successful reservation.
        return reserved;
      }

      release(reserved);
    }
  }

  // Failed
  return {};
}

#define SIZE_64K  ((uint64_t) UCONST64(      0x10000))
#define SIZE_256M ((uint64_t) UCONST64(   0x10000000))
#define SIZE_32G  ((uint64_t) UCONST64(  0x800000000))

// Helper for heap allocation. Returns an array with addresses
// (OS-specific) which are suited for disjoint base mode. Array is
// null terminated.
static char** get_attach_addresses_for_disjoint_mode() {
  static uint64_t addresses[] = {
     2 * SIZE_32G,
     3 * SIZE_32G,
     4 * SIZE_32G,
     8 * SIZE_32G,
    10 * SIZE_32G,
     1 * SIZE_64K * SIZE_32G,
     2 * SIZE_64K * SIZE_32G,
     3 * SIZE_64K * SIZE_32G,
     4 * SIZE_64K * SIZE_32G,
    16 * SIZE_64K * SIZE_32G,
    32 * SIZE_64K * SIZE_32G,
    34 * SIZE_64K * SIZE_32G,
    0
  };

  // Sort out addresses smaller than HeapBaseMinAddress. This assumes
  // the array is sorted.
  uint i = 0;
  while (addresses[i] != 0 &&
         (addresses[i] < OopEncodingHeapMax || addresses[i] < HeapBaseMinAddress)) {
    i++;
  }
  uint start = i;

  // Avoid more steps than requested.
  i = 0;
  while (addresses[start+i] != 0) {
    if (i == HeapSearchSteps) {
      addresses[start+i] = 0;
      break;
    }
    i++;
  }

  return (char**) &addresses[start];
}

// Create protection page at the beginning of the space.
static ReservedSpace establish_noaccess_prefix(const ReservedSpace& reserved, size_t noaccess_prefix) {
  assert(reserved.alignment() >= os::vm_page_size(), "must be at least page size big");
  assert(reserved.is_reserved(), "should only be called on a reserved memory area");

  if (reserved.end() > (char *)OopEncodingHeapMax) {
    if (true
        WIN64_ONLY(&& !UseLargePages)
        AIX_ONLY(&& (os::Aix::supports_64K_mmap_pages() || os::vm_page_size() == 4*K))) {
      // Protect memory at the base of the allocated region.
      if (!os::protect_memory(reserved.base(), noaccess_prefix, os::MEM_PROT_NONE, reserved.special())) {
        fatal("cannot protect protection page");
      }
      log_debug(gc, heap, coops)("Protected page at the reserved heap base: "
                                 PTR_FORMAT " / %zd bytes",
                                 p2i(reserved.base()),
                                 noaccess_prefix);
      assert(CompressedOops::use_implicit_null_checks() == true, "not initialized?");
    } else {
      CompressedOops::set_use_implicit_null_checks(false);
    }
  }

  return reserved.last_part(noaccess_prefix);
}

ReservedHeapSpace HeapReserver::Instance::reserve_compressed_oops_heap(const size_t size, size_t alignment, size_t page_size) {
  const size_t noaccess_prefix_size = lcm(os::vm_page_size(), alignment);
  const size_t granularity = os::vm_allocation_granularity();

  assert(size + noaccess_prefix_size <= OopEncodingHeapMax,  "can not allocate compressed oop heap for this size");
  assert(is_aligned(size, granularity), "size not aligned to os::vm_allocation_granularity()");

  assert(alignment >= os::vm_page_size(), "alignment too small");
  assert(is_aligned(alignment, granularity), "alignment not aligned to os::vm_allocation_granularity()");
  assert(is_power_of_2(alignment), "not a power of 2");

  // The necessary attach point alignment for generated wish addresses.
  // This is needed to increase the chance of attaching for mmap and shmat.
  // AIX is the only platform that uses System V shm for reserving virtual memory.
  // In this case, the required alignment of the allocated size (64K) and the alignment
  // of possible start points of the memory region (256M) differ.
  // This is not reflected by os_allocation_granularity().
  // The logic here is dual to the one in pd_reserve_memory in os_aix.cpp
  const size_t os_attach_point_alignment =
    AIX_ONLY(os::vm_page_size() == 4*K ? 4*K : 256*M)
    NOT_AIX(os::vm_allocation_granularity());

  const size_t attach_point_alignment = lcm(alignment, os_attach_point_alignment);

  char* aligned_heap_base_min_address = align_up((char*)HeapBaseMinAddress, alignment);
  size_t noaccess_prefix = ((aligned_heap_base_min_address + size) > (char*)OopEncodingHeapMax) ?
    noaccess_prefix_size : 0;

  ReservedSpace reserved{};

  // Attempt to alloc at user-given address.
  if (!FLAG_IS_DEFAULT(HeapBaseMinAddress)) {
    reserved = try_reserve_memory(size + noaccess_prefix, alignment, page_size, aligned_heap_base_min_address);
    if (reserved.base() != aligned_heap_base_min_address) { // Enforce this exact address.
      release(reserved);
      reserved = {};
    }
  }

  // Keep heap at HeapBaseMinAddress.
  if (!reserved.is_reserved()) {

    // Try to allocate the heap at addresses that allow efficient oop compression.
    // Different schemes are tried, in order of decreasing optimization potential.
    //
    // For this, try_reserve_heap() is called with the desired heap base addresses.
    // A call into the os layer to allocate at a given address can return memory
    // at a different address than requested.  Still, this might be memory at a useful
    // address. try_reserve_heap() always returns this allocated memory, as only here
    // the criteria for a good heap are checked.

    // Attempt to allocate so that we can run without base and scale (32-Bit unscaled compressed oops).
    // Give it several tries from top of range to bottom.
    if (aligned_heap_base_min_address + size <= (char *)UnscaledOopHeapMax) {

      // Calc address range within we try to attach (range of possible start addresses).
      char* const highest_start = align_down((char *)UnscaledOopHeapMax - size, attach_point_alignment);
      char* const lowest_start  = align_up(aligned_heap_base_min_address, attach_point_alignment);
      reserved = try_reserve_range(highest_start, lowest_start, attach_point_alignment,
                                   aligned_heap_base_min_address, (char *)UnscaledOopHeapMax, size, alignment, page_size);
    }

    // zerobased: Attempt to allocate in the lower 32G.
    char *zerobased_max = (char *)OopEncodingHeapMax;

    // Give it several tries from top of range to bottom.
    if (aligned_heap_base_min_address + size <= zerobased_max && // Zerobased theoretical possible.
        ((!reserved.is_reserved()) ||                            // No previous try succeeded.
         (reserved.end() > zerobased_max))) {                    // Unscaled delivered an arbitrary address.

      // Release previous reservation
      release(reserved);

      // Calc address range within we try to attach (range of possible start addresses).
      char *const highest_start = align_down(zerobased_max - size, attach_point_alignment);
      // Need to be careful about size being guaranteed to be less
      // than UnscaledOopHeapMax due to type constraints.
      char *lowest_start = aligned_heap_base_min_address;
      uint64_t unscaled_end = UnscaledOopHeapMax - size;
      if (unscaled_end < UnscaledOopHeapMax) { // unscaled_end wrapped if size is large
        lowest_start = MAX2(lowest_start, (char*)unscaled_end);
      }
      lowest_start = align_up(lowest_start, attach_point_alignment);
      reserved = try_reserve_range(highest_start, lowest_start, attach_point_alignment,
                                   aligned_heap_base_min_address, zerobased_max, size, alignment, page_size);
    }

    // Now we go for heaps with base != 0.  We need a noaccess prefix to efficiently
    // implement null checks.
    noaccess_prefix = noaccess_prefix_size;

    // Try to attach at addresses that are aligned to OopEncodingHeapMax. Disjointbase mode.
    char** addresses = get_attach_addresses_for_disjoint_mode();
    int i = 0;
    while ((addresses[i] != nullptr) &&       // End of array not yet reached.
           ((!reserved.is_reserved()) ||      // No previous try succeeded.
           (reserved.end() > zerobased_max && // Not zerobased or unscaled address.
                                              // Not disjoint address.
            !CompressedOops::is_disjoint_heap_base_address((address)reserved.base())))) {

      // Release previous reservation
      release(reserved);

      char* const attach_point = addresses[i];
      assert(attach_point >= aligned_heap_base_min_address, "Flag support broken");
      reserved = try_reserve_memory(size + noaccess_prefix, alignment, page_size, attach_point);
      i++;
    }

    // Last, desperate try without any placement.
    if (!reserved.is_reserved()) {
      log_trace(gc, heap, coops)("Trying to allocate at address null heap of size 0x%zx", size + noaccess_prefix);
      assert(alignment >= os::vm_page_size(), "Unexpected");
      reserved = reserve_memory(size + noaccess_prefix, alignment, page_size);
    }
  }

  // No more reserve attempts

  if (reserved.is_reserved()) {
    // Successfully found and reserved memory for the heap.

    if (reserved.size() > size) {
      // We reserved heap memory with a noaccess prefix.

      assert(reserved.size() == size + noaccess_prefix, "Prefix should be included");
      // It can happen we get a zerobased/unscaled heap with noaccess prefix,
      // if we had to try at arbitrary address.
      reserved = establish_noaccess_prefix(reserved, noaccess_prefix);
      assert(reserved.size() == size, "Prefix should be gone");
      return ReservedHeapSpace(reserved, noaccess_prefix);
    }

    // We reserved heap memory without a noaccess prefix.
    return ReservedHeapSpace(reserved, 0 /* noaccess_prefix */);
  }

  // Failed
  return {};
}

#endif // _LP64

ReservedHeapSpace HeapReserver::Instance::reserve_heap(size_t size, size_t alignment, size_t page_size) {
  if (UseCompressedOops) {
#ifdef _LP64
    return reserve_compressed_oops_heap(size, alignment, page_size);
#endif
  } else {
    return reserve_uncompressed_oops_heap(size, alignment, page_size);
  }
}

ReservedHeapSpace HeapReserver::reserve(size_t size, size_t alignment, size_t page_size, const char* heap_allocation_directory) {
  sanity_check_arguments(size, alignment, page_size);

  assert(alignment != 0, "Precondition");
  assert(is_aligned(size, alignment), "Precondition");

  Instance instance(heap_allocation_directory);

  return instance.reserve_heap(size, alignment, page_size);
}
