Commit 605271bd authored by Chris Fallin's avatar Chris Fallin
Browse files

Bug 1701620 part 4 - Fix memory support for WASI. r=jandem,sfink

WASI lacks of support many memory stuff like mmap, memory protections and etc, but
it has malloc so we can use it instead. Also, here we are stubbing out all
uses of the missing WASI memory functionality.

Differential Revision: https://phabricator.services.mozilla.com/D110075
parent 0ba7033c
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -11,6 +11,8 @@

#if defined(XP_WIN)
#  include "util/Windows.h"
#elif defined(__wasi__)
// Nothing.
#elif defined(XP_UNIX) && !defined(XP_DARWIN)
#  include <signal.h>
#  include <sys/types.h>
@@ -121,6 +123,8 @@ bool MemoryProtectionExceptionHandler::isDisabled() {
#elif !defined(MOZ_DIAGNOSTIC_ASSERT_ENABLED)
  // Disable the exception handler for Beta and Release builds.
  return true;
#elif defined(__wasi__)
  return true;
#else
  return false;
#endif
@@ -232,6 +236,12 @@ void MemoryProtectionExceptionHandler::uninstall() {
  }
}

#elif defined(__wasi__)

bool MemoryProtectionExceptionHandler::install() { return true; }

void MemoryProtectionExceptionHandler::uninstall() {}

#elif defined(XP_UNIX) && !defined(XP_DARWIN)

static struct sigaction sPrevSEGVHandler = {};
+1 −1
Original line number Diff line number Diff line
@@ -206,7 +206,7 @@
#include <iterator>
#include <string.h>
#include <utility>
#ifndef XP_WIN
#if !defined(XP_WIN) && !defined(__wasi__)
#  include <sys/mman.h>
#  include <unistd.h>
#endif
+69 −16
Original line number Diff line number Diff line
@@ -20,6 +20,10 @@
#  include "util/Windows.h"
#  include <psapi.h>

#elif defined(__wasi__)

/* nothing */

#else

#  include <algorithm>
@@ -140,6 +144,15 @@ enum class PageAccess : DWORD {
  ReadExecute = PAGE_EXECUTE_READ,
  ReadWriteExecute = PAGE_EXECUTE_READWRITE,
};
#elif defined(__wasi__)
enum class PageAccess : int {
  None = 0,
  Read = 0,
  ReadWrite = 0,
  Execute = 0,
  ReadExecute = 0,
  ReadWriteExecute = 0,
};
#else
enum class PageAccess : int {
  None = PROT_NONE,
@@ -155,7 +168,9 @@ template <bool AlwaysGetNew = true>
static bool TryToAlignChunk(void** aRegion, void** aRetainedRegion,
                            size_t length, size_t alignment);

#ifndef __wasi__
static void* MapAlignedPagesSlow(size_t length, size_t alignment);
#endif  // wasi
static void* MapAlignedPagesLastDitch(size_t length, size_t alignment);

#ifdef JS_64BIT
@@ -180,6 +195,14 @@ static inline void* MapInternal(void* desired, size_t length) {
  DWORD flags =
      (commit == Commit::Yes ? MEM_RESERVE | MEM_COMMIT : MEM_RESERVE);
  region = VirtualAlloc(desired, length, flags, DWORD(prot));
#elif defined(__wasi__)
  if (int err = posix_memalign(&region, gc::SystemPageSize(), length)) {
    MOZ_RELEASE_ASSERT(err == ENOMEM);
    return nullptr;
  }
  if (region) {
    memset(region, 0, length);
  }
#else
  int flags = MAP_PRIVATE | MAP_ANON;
  region = MozTaggedAnonymousMmap(desired, length, int(prot), flags, -1, 0,
@@ -197,6 +220,8 @@ static inline void UnmapInternal(void* region, size_t length) {

#ifdef XP_WIN
  MOZ_RELEASE_ASSERT(VirtualFree(region, 0, MEM_RELEASE) != 0);
#elif defined(__wasi__)
  free(region);
#else
  if (munmap(region, length)) {
    MOZ_RELEASE_ASSERT(errno == ENOMEM);
@@ -407,6 +432,17 @@ void* MapAlignedPages(size_t length, size_t alignment) {
    alignment = allocGranularity;
  }

#ifdef __wasi__
  void* region = nullptr;
  if (int err = posix_memalign(&region, alignment, length)) {
    MOZ_ASSERT(err == ENOMEM);
    return nullptr;
  }
  MOZ_ASSERT(region != nullptr);
  memset(region, 0, length);
  return region;
#else

#  ifdef JS_64BIT
  // Use the scattershot allocator if the address range is large enough.
  if (UsingScattershotAllocator()) {
@@ -460,6 +496,7 @@ void* MapAlignedPages(size_t length, size_t alignment) {
  // At this point we should either have an aligned region or nullptr.
  MOZ_ASSERT(OffsetFromAligned(region, alignment) == 0);
  return region;
#endif  // !__wasi__
}

#ifdef JS_64BIT
@@ -546,6 +583,7 @@ static void* MapAlignedPagesRandom(size_t length, size_t alignment) {

#endif  // defined(JS_64BIT)

#ifndef __wasi__
static void* MapAlignedPagesSlow(size_t length, size_t alignment) {
  void* alignedRegion = nullptr;
  do {
@@ -584,6 +622,7 @@ static void* MapAlignedPagesSlow(size_t length, size_t alignment) {

  return alignedRegion;
}
#endif  // wasi

/*
 * In a low memory or high fragmentation situation, alignable chunks of the
@@ -767,6 +806,8 @@ bool MarkPagesUnusedSoft(void* region, size_t length) {
#if defined(XP_WIN)
  return VirtualAlloc(region, length, MEM_RESET,
                      DWORD(PageAccess::ReadWrite)) == region;
#elif defined(__wasi__)
  return 0;
#else
  int status;
  do {
@@ -838,6 +879,8 @@ size_t GetPageFaultCount() {
    return 0;
  }
  return pmc.PageFaultCount;
#elif defined(__wasi__)
  return 0;
#else
  struct rusage usage;
  int err = getrusage(RUSAGE_SELF, &usage);
@@ -850,6 +893,9 @@ size_t GetPageFaultCount() {

void* AllocateMappedContent(int fd, size_t offset, size_t length,
                            size_t alignment) {
#ifdef __wasi__
  MOZ_CRASH("Not yet supported for WASI");
#else
  if (length == 0 || alignment == 0 || offset % alignment != 0 ||
      std::max(alignment, allocGranularity) %
              std::min(alignment, allocGranularity) !=
@@ -941,9 +987,13 @@ void* AllocateMappedContent(int fd, size_t offset, size_t length,
#  endif

  return map + (offset - alignedOffset);
#endif  // __wasi__
}

void DeallocateMappedContent(void* region, size_t length) {
#ifdef __wasi__
  MOZ_CRASH("Not yet supported for WASI");
#else
  if (!region) {
    return;
  }
@@ -964,6 +1014,7 @@ void DeallocateMappedContent(void* region, size_t length) {
    MOZ_RELEASE_ASSERT(errno == ENOMEM);
  }
#  endif
#endif  // __wasi__
}

static inline void ProtectMemory(void* region, size_t length, PageAccess prot) {
@@ -973,6 +1024,8 @@ static inline void ProtectMemory(void* region, size_t length, PageAccess prot) {
  DWORD oldProtect;
  MOZ_RELEASE_ASSERT(VirtualProtect(region, length, DWORD(prot), &oldProtect) !=
                     0);
#elif defined(__wasi__)
  /* nothing */
#else
  MOZ_RELEASE_ASSERT(mprotect(region, length, int(prot)) == 0);
#endif
+29 −4
Original line number Diff line number Diff line
@@ -34,6 +34,8 @@
#ifdef XP_WIN
#  include "mozilla/StackWalk_windows.h"
#  include "mozilla/WindowsVersion.h"
#elif defined(__wasi__)
// Nothing.
#else
#  include <sys/mman.h>
#  include <unistd.h>
@@ -324,7 +326,20 @@ static void DecommitPages(void* addr, size_t bytes) {
    MOZ_CRASH("DecommitPages failed");
  }
}
#else  // !XP_WIN
#elif defined(__wasi__)
static void* ReserveProcessExecutableMemory(size_t bytes) {
  MOZ_CRASH("NYI for WASI.");
  return nullptr;
}
[[nodiscard]] static bool CommitPages(void* addr, size_t bytes,
                                      ProtectionSetting protection) {
  MOZ_CRASH("NYI for WASI.");
  return false;
}
static void DecommitPages(void* addr, size_t bytes) {
  MOZ_CRASH("NYI for WASI.");
}
#else  // !XP_WIN && !__wasi__
#  ifndef MAP_NORESERVE
#    define MAP_NORESERVE 0
#  endif
@@ -556,6 +571,9 @@ class ProcessExecutableMemory {
  }

  void release() {
#if defined(__wasi__)
    MOZ_ASSERT(!initialized());
#else
    MOZ_ASSERT(initialized());
    MOZ_ASSERT(pages_.empty());
    MOZ_ASSERT(pagesAllocated_ == 0);
@@ -563,6 +581,7 @@ class ProcessExecutableMemory {
    base_ = nullptr;
    rng_.reset();
    MOZ_ASSERT(!initialized());
#endif
  }

  void assertValidAddress(void* p, size_t bytes) const {
@@ -709,6 +728,8 @@ bool js::jit::InitProcessExecutableMemory() {
#ifdef JS_CODEGEN_ARM64
  // Initialize instruction cache flushing.
  vixl::CPU::SetUp();
#elif defined(__wasi__)
  return true;
#endif
  return execMemory.init();
}
@@ -772,6 +793,9 @@ bool js::jit::ReprotectRegion(void* start, size_t size,
  // We use the C++ fence here -- and not AtomicOperations::fenceSeqCst() --
  // primarily because ReprotectRegion will be called while we construct our own
  // jitted atomics.  But the C++ fence is sufficient and correct, too.
#ifdef __wasi__
  MOZ_CRASH("NYI FOR WASI.");
#else
  std::atomic_thread_fence(std::memory_order_seq_cst);

#  ifdef XP_WIN
@@ -786,6 +810,7 @@ bool js::jit::ReprotectRegion(void* start, size_t size,
    return false;
  }
#  endif
#endif  // __wasi__

  execMemory.assertValidAddress(pageStart, size);
  return true;
+18 −0
Original line number Diff line number Diff line
@@ -13,6 +13,8 @@
#if defined(XP_WIN)
#  include "util/Windows.h"
#  include <psapi.h>
#elif defined(__wasi__)
// Nothing.
#else
#  include <algorithm>
#  include <errno.h>
@@ -296,6 +298,22 @@ void unmapPages(void* p, size_t size) {
  MOZ_ALWAYS_TRUE(VirtualFree(p, 0, MEM_RELEASE));
}

#elif defined(__wasi__)

void* mapMemoryAt(void* desired, size_t length) { return nullptr; }

void* mapMemory(size_t length) {
  void* addr = nullptr;
  if (int err = posix_memalign(&addr, js::gc::SystemPageSize(), length)) {
    MOZ_ASSERT(err == ENOMEM);
  }
  MOZ_ASSERT(addr);
  memset(addr, 0, length);
  return addr;
}

void unmapPages(void* p, size_t size) { free(p); }

#else

void* mapMemoryAt(void* desired, size_t length) {
Loading