[vm] Deduplicate POSIX-based memory allocation code

The Android, Linux, and macOS VirtualMemory implementations were
identical and using the same POSIX-standardized interfaces, so
deduplicate them into a common virtual_memory_posix.cc implementation.

Change-Id: I58a2aaa959aac69af52d9faba88865a4ef20d004
Reviewed-on: https://dart-review.googlesource.com/c/91080
Commit-Queue: Ryan Macnak <rmacnak@google.com>
Reviewed-by: Siva Annamalai <asiva@google.com>
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Auto-Submit: Matthew Dempsky <mdempsky@google.com>
diff --git a/runtime/vm/virtual_memory_android.cc b/runtime/vm/virtual_memory_android.cc
deleted file mode 100644
index 1ebce26..0000000
--- a/runtime/vm/virtual_memory_android.cc
+++ /dev/null
@@ -1,143 +0,0 @@
-// Copyright (c) 2012, 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/globals.h"
-#if defined(HOST_OS_ANDROID)
-
-#include "vm/virtual_memory.h"
-
-#include <errno.h>
-#include <sys/mman.h>
-#include <unistd.h>
-
-#include "platform/assert.h"
-#include "platform/utils.h"
-
-#include "vm/isolate.h"
-
-namespace dart {
-
-// standard MAP_FAILED causes "error: use of old-style cast" as it
-// defines MAP_FAILED as ((void *) -1)
-#undef MAP_FAILED
-#define MAP_FAILED reinterpret_cast<void*>(-1)
-
-uword VirtualMemory::page_size_ = 0;
-
-void VirtualMemory::Init() {
-  page_size_ = getpagesize();
-}
-
-static void unmap(void* address, intptr_t size) {
-  if (size == 0) {
-    return;
-  }
-
-  if (munmap(address, size) != 0) {
-    int error = errno;
-    const int kBufferSize = 1024;
-    char error_buf[kBufferSize];
-    FATAL2("munmap error: %d (%s)", error,
-           Utils::StrError(error, error_buf, kBufferSize));
-  }
-}
-
-VirtualMemory* VirtualMemory::Allocate(intptr_t size,
-                                       bool is_executable,
-                                       const char* name) {
-  ASSERT(Utils::IsAligned(size, page_size_));
-  int prot = PROT_READ | PROT_WRITE | (is_executable ? PROT_EXEC : 0);
-  void* address = mmap(NULL, size, prot, MAP_PRIVATE | MAP_ANON, -1, 0);
-  if (address == MAP_FAILED) {
-    return NULL;
-  }
-  MemoryRegion region(address, size);
-  return new VirtualMemory(region, region);
-}
-
-VirtualMemory* VirtualMemory::AllocateAligned(intptr_t size,
-                                              intptr_t alignment,
-                                              bool is_executable,
-                                              const char* name) {
-  ASSERT(Utils::IsAligned(size, page_size_));
-  ASSERT(Utils::IsAligned(alignment, page_size_));
-  intptr_t allocated_size = size + alignment;
-  int prot = PROT_READ | PROT_WRITE | (is_executable ? PROT_EXEC : 0);
-  void* address =
-      mmap(NULL, allocated_size, prot, MAP_PRIVATE | MAP_ANON, -1, 0);
-  if (address == MAP_FAILED) {
-    return NULL;
-  }
-
-  uword base = reinterpret_cast<uword>(address);
-  uword aligned_base = Utils::RoundUp(base, alignment);
-  ASSERT(base <= aligned_base);
-
-  if (base != aligned_base) {
-    uword extra_leading_size = aligned_base - base;
-    unmap(reinterpret_cast<void*>(base), extra_leading_size);
-    allocated_size -= extra_leading_size;
-  }
-
-  if (allocated_size != size) {
-    uword extra_trailing_size = allocated_size - size;
-    unmap(reinterpret_cast<void*>(aligned_base + size), extra_trailing_size);
-  }
-
-  MemoryRegion region(reinterpret_cast<void*>(aligned_base), size);
-  return new VirtualMemory(region, region);
-}
-
-VirtualMemory::~VirtualMemory() {
-  if (vm_owns_region()) {
-    unmap(reserved_.pointer(), reserved_.size());
-  }
-}
-
-bool VirtualMemory::FreeSubSegment(void* address,
-                                   intptr_t size) {
-  unmap(address, size);
-  return true;
-}
-
-void VirtualMemory::Protect(void* address, intptr_t size, Protection mode) {
-#if defined(DEBUG)
-  Thread* thread = Thread::Current();
-  ASSERT((thread == nullptr) || thread->IsMutatorThread() ||
-         thread->isolate()->mutator_thread()->IsAtSafepoint());
-#endif
-  uword start_address = reinterpret_cast<uword>(address);
-  uword end_address = start_address + size;
-  uword page_address = Utils::RoundDown(start_address, PageSize());
-  int prot = 0;
-  switch (mode) {
-    case kNoAccess:
-      prot = PROT_NONE;
-      break;
-    case kReadOnly:
-      prot = PROT_READ;
-      break;
-    case kReadWrite:
-      prot = PROT_READ | PROT_WRITE;
-      break;
-    case kReadExecute:
-      prot = PROT_READ | PROT_EXEC;
-      break;
-    case kReadWriteExecute:
-      prot = PROT_READ | PROT_WRITE | PROT_EXEC;
-      break;
-  }
-  if (mprotect(reinterpret_cast<void*>(page_address),
-               end_address - page_address, prot) != 0) {
-    int error = errno;
-    const int kBufferSize = 1024;
-    char error_buf[kBufferSize];
-    FATAL2("mprotect error: %d (%s)", error,
-           Utils::StrError(error, error_buf, kBufferSize));
-  }
-}
-
-}  // namespace dart
-
-#endif  // defined(HOST_OS_ANDROID)
diff --git a/runtime/vm/virtual_memory_linux.cc b/runtime/vm/virtual_memory_linux.cc
deleted file mode 100644
index bd76de5..0000000
--- a/runtime/vm/virtual_memory_linux.cc
+++ /dev/null
@@ -1,143 +0,0 @@
-// Copyright (c) 2012, 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/globals.h"
-#if defined(HOST_OS_LINUX)
-
-#include "vm/virtual_memory.h"
-
-#include <errno.h>
-#include <sys/mman.h>
-#include <unistd.h>
-
-#include "platform/assert.h"
-#include "platform/utils.h"
-
-#include "vm/isolate.h"
-
-namespace dart {
-
-// standard MAP_FAILED causes "error: use of old-style cast" as it
-// defines MAP_FAILED as ((void *) -1)
-#undef MAP_FAILED
-#define MAP_FAILED reinterpret_cast<void*>(-1)
-
-uword VirtualMemory::page_size_ = 0;
-
-void VirtualMemory::Init() {
-  page_size_ = getpagesize();
-}
-
-static void unmap(void* address, intptr_t size) {
-  if (size == 0) {
-    return;
-  }
-
-  if (munmap(address, size) != 0) {
-    int error = errno;
-    const int kBufferSize = 1024;
-    char error_buf[kBufferSize];
-    FATAL2("munmap error: %d (%s)", error,
-           Utils::StrError(error, error_buf, kBufferSize));
-  }
-}
-
-VirtualMemory* VirtualMemory::Allocate(intptr_t size,
-                                       bool is_executable,
-                                       const char* name) {
-  ASSERT(Utils::IsAligned(size, page_size_));
-  int prot = PROT_READ | PROT_WRITE | (is_executable ? PROT_EXEC : 0);
-  void* address = mmap(NULL, size, prot, MAP_PRIVATE | MAP_ANON, -1, 0);
-  if (address == MAP_FAILED) {
-    return NULL;
-  }
-  MemoryRegion region(address, size);
-  return new VirtualMemory(region, region);
-}
-
-VirtualMemory* VirtualMemory::AllocateAligned(intptr_t size,
-                                              intptr_t alignment,
-                                              bool is_executable,
-                                              const char* name) {
-  ASSERT(Utils::IsAligned(size, page_size_));
-  ASSERT(Utils::IsAligned(alignment, page_size_));
-  intptr_t allocated_size = size + alignment;
-  int prot = PROT_READ | PROT_WRITE | (is_executable ? PROT_EXEC : 0);
-  void* address =
-      mmap(NULL, allocated_size, prot, MAP_PRIVATE | MAP_ANON, -1, 0);
-  if (address == MAP_FAILED) {
-    return NULL;
-  }
-
-  uword base = reinterpret_cast<uword>(address);
-  uword aligned_base = Utils::RoundUp(base, alignment);
-  ASSERT(base <= aligned_base);
-
-  if (base != aligned_base) {
-    uword extra_leading_size = aligned_base - base;
-    unmap(reinterpret_cast<void*>(base), extra_leading_size);
-    allocated_size -= extra_leading_size;
-  }
-
-  if (allocated_size != size) {
-    uword extra_trailing_size = allocated_size - size;
-    unmap(reinterpret_cast<void*>(aligned_base + size), extra_trailing_size);
-  }
-
-  MemoryRegion region(reinterpret_cast<void*>(aligned_base), size);
-  return new VirtualMemory(region, region);
-}
-
-VirtualMemory::~VirtualMemory() {
-  if (vm_owns_region()) {
-    unmap(reserved_.pointer(), reserved_.size());
-  }
-}
-
-bool VirtualMemory::FreeSubSegment(void* address,
-                                   intptr_t size) {
-  unmap(address, size);
-  return true;
-}
-
-void VirtualMemory::Protect(void* address, intptr_t size, Protection mode) {
-#if defined(DEBUG)
-  Thread* thread = Thread::Current();
-  ASSERT((thread == nullptr) || thread->IsMutatorThread() ||
-         thread->isolate()->mutator_thread()->IsAtSafepoint());
-#endif
-  uword start_address = reinterpret_cast<uword>(address);
-  uword end_address = start_address + size;
-  uword page_address = Utils::RoundDown(start_address, PageSize());
-  int prot = 0;
-  switch (mode) {
-    case kNoAccess:
-      prot = PROT_NONE;
-      break;
-    case kReadOnly:
-      prot = PROT_READ;
-      break;
-    case kReadWrite:
-      prot = PROT_READ | PROT_WRITE;
-      break;
-    case kReadExecute:
-      prot = PROT_READ | PROT_EXEC;
-      break;
-    case kReadWriteExecute:
-      prot = PROT_READ | PROT_WRITE | PROT_EXEC;
-      break;
-  }
-  if (mprotect(reinterpret_cast<void*>(page_address),
-               end_address - page_address, prot) != 0) {
-    int error = errno;
-    const int kBufferSize = 1024;
-    char error_buf[kBufferSize];
-    FATAL2("mprotect error: %d (%s)", error,
-           Utils::StrError(error, error_buf, kBufferSize));
-  }
-}
-
-}  // namespace dart
-
-#endif  // defined(HOST_OS_LINUX)
diff --git a/runtime/vm/virtual_memory_macos.cc b/runtime/vm/virtual_memory_posix.cc
similarity index 95%
rename from runtime/vm/virtual_memory_macos.cc
rename to runtime/vm/virtual_memory_posix.cc
index dc75b44..637548f 100644
--- a/runtime/vm/virtual_memory_macos.cc
+++ b/runtime/vm/virtual_memory_posix.cc
@@ -3,7 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 #include "vm/globals.h"
-#if defined(HOST_OS_MACOS)
+#if defined(HOST_OS_ANDROID) || defined(HOST_OS_LINUX) || defined(HOST_OS_MACOS)
 
 #include "vm/virtual_memory.h"
 
@@ -140,4 +140,4 @@
 
 }  // namespace dart
 
-#endif  // defined(HOST_OS_MACOS)
+#endif  // defined(HOST_OS_ANDROID) || defined(HOST_OS_LINUX) || defined(HOST_OS_MACOS)
diff --git a/runtime/vm/vm_sources.gni b/runtime/vm/vm_sources.gni
index 9bfbb25..9e4dc96 100644
--- a/runtime/vm/vm_sources.gni
+++ b/runtime/vm/vm_sources.gni
@@ -345,10 +345,8 @@
   "v8_snapshot_writer.h",
   "virtual_memory.cc",
   "virtual_memory.h",
-  "virtual_memory_android.cc",
   "virtual_memory_fuchsia.cc",
-  "virtual_memory_linux.cc",
-  "virtual_memory_macos.cc",
+  "virtual_memory_posix.cc",
   "virtual_memory_win.cc",
   "visitor.h",
   "zone.cc",