[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",