Skip to content

Commit

Permalink
Use mmap, mprotect instead of calloc on POSIX system
Browse files Browse the repository at this point in the history
* Fix default memory maximium size bug

Signed-off-by: Seonghyun Kim <sh8281.kim@samsung.com>
  • Loading branch information
ksh8281 authored and clover2123 committed Sep 20, 2023
1 parent 8fc5c43 commit a91d3ce
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 8 deletions.
70 changes: 65 additions & 5 deletions src/runtime/Memory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@
#include "runtime/Instance.h"
#include "runtime/Module.h"

#if defined(OS_POSIX)
#define WALRUS_USE_MMAP
#include <sys/mman.h>
#endif

namespace Walrus {

Memory* Memory::createMemory(Store* store, uint64_t initialSizeInByte, uint64_t maximumSizeInByte)
Expand All @@ -32,30 +37,85 @@ Memory* Memory::createMemory(Store* store, uint64_t initialSizeInByte, uint64_t

Memory::Memory(uint64_t initialSizeInByte, uint64_t maximumSizeInByte)
: m_sizeInByte(initialSizeInByte)
, m_reservedSizeInByte(0)
, m_maximumSizeInByte(maximumSizeInByte)
, m_buffer(reinterpret_cast<uint8_t*>(calloc(1, initialSizeInByte)))
, m_buffer(nullptr)
{
RELEASE_ASSERT(initialSizeInByte <= std::numeric_limits<size_t>::max());
#if defined(WALRUS_USE_MMAP)
if (m_maximumSizeInByte) {
#ifndef WALRUS_32_MEMORY_INITIAL_MMAP_RESERVED_ADDRESS_SIZE
#define WALRUS_32_MEMORY_INITIAL_MMAP_RESERVED_ADDRESS_SIZE (1024 * 1024 * 64)
#endif
#ifndef WALRUS_64_MEMORY_INITIAL_MMAP_RESERVED_ADDRESS_SIZE
#define WALRUS_64_MEMORY_INITIAL_MMAP_RESERVED_ADDRESS_SIZE (1024 * 1024 * 512)
#endif
uint64_t initialReservedSize =
#if defined(WALRUS_32)
WALRUS_32_MEMORY_INITIAL_MMAP_RESERVED_ADDRESS_SIZE;
#else
WALRUS_64_MEMORY_INITIAL_MMAP_RESERVED_ADDRESS_SIZE;
#endif
m_reservedSizeInByte = std::min(initialReservedSize, m_maximumSizeInByte);
m_buffer = reinterpret_cast<uint8_t*>(mmap(NULL, m_reservedSizeInByte, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0));
RELEASE_ASSERT(MAP_FAILED != m_buffer);
mprotect(m_buffer, initialSizeInByte, (PROT_READ | PROT_WRITE));
} else {
m_reservedSizeInByte = 0;
m_buffer = nullptr;
}
#else
m_buffer = reinterpret_cast<uint8_t*>(calloc(1, initialSizeInByte));
m_reservedSizeInByte = initialSizeInByte;
RELEASE_ASSERT(m_buffer);
#endif
}

Memory::~Memory()
{
#if defined(WALRUS_USE_MMAP)
if (m_buffer) {
munmap(m_buffer, m_reservedSizeInByte);
}
#else
ASSERT(!!m_buffer);
free(m_buffer);
#endif
}

bool Memory::grow(uint64_t growSizeInByte)
{
uint64_t newSizeInByte = growSizeInByte + m_sizeInByte;
if (newSizeInByte > m_sizeInByte && newSizeInByte <= m_maximumSizeInByte) {
uint8_t* newBuffer = reinterpret_cast<uint8_t*>(calloc(1, newSizeInByte));
if (newBuffer) {
#if defined(WALRUS_USE_MMAP)
if (newSizeInByte <= m_reservedSizeInByte) {
mprotect(m_buffer + m_sizeInByte, growSizeInByte, (PROT_READ | PROT_WRITE));
m_sizeInByte = newSizeInByte;
} else {
auto newReservedSizeInByte = std::min(newSizeInByte * 2, m_maximumSizeInByte);
auto newBuffer = reinterpret_cast<uint8_t*>(mmap(NULL, newReservedSizeInByte, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0));
if (MAP_FAILED == newBuffer) {
return false;
}
mprotect(newBuffer, newSizeInByte, (PROT_READ | PROT_WRITE));
memcpy(newBuffer, m_buffer, m_sizeInByte);
free(m_buffer);
munmap(m_buffer, m_reservedSizeInByte);
m_buffer = newBuffer;
m_sizeInByte = newSizeInByte;
return true;
m_reservedSizeInByte = newReservedSizeInByte;
}
#else
uint8_t* newBuffer = reinterpret_cast<uint8_t*>(calloc(1, newSizeInByte));
if (newBuffer == nullptr || newSizeInByte >= std::numeric_limits<size_t>::max()) {
return false;
}
m_reservedSizeInByte = newSizeInByte;
memcpy(newBuffer, m_buffer, m_sizeInByte);
free(m_buffer);
m_buffer = newBuffer;
m_sizeInByte = newSizeInByte;
#endif
return true;
} else if (newSizeInByte == m_sizeInByte) {
return true;
}
Expand Down
1 change: 1 addition & 0 deletions src/runtime/Memory.h
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ class Memory : public Extern {
inline void fillMemory(uint32_t start, uint8_t value, uint32_t size);

uint64_t m_sizeInByte;
uint64_t m_reservedSizeInByte;
uint64_t m_maximumSizeInByte;
uint8_t* m_buffer;
};
Expand Down
3 changes: 2 additions & 1 deletion test/basic/memory.wast
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,5 @@
(memory 0)
(func (export "grow") (param i32) (result i32) (memory.grow (local.get 0)))
)
(assert_return (invoke "grow" (i32.const 0x10000)) (i32.const 0))
(assert_return (invoke "grow" (i32.const 0x1000)) (i32.const 0))
(assert_return (invoke "grow" (i32.const 0x10000)) (i32.const -1))
6 changes: 4 additions & 2 deletions third_party/wabt/src/walrus/binary-reader-walrus.cc
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,8 @@ class BinaryReaderDelegateWalrus: public BinaryReaderDelegate {
}
Result OnImportMemory(Index import_index, nonstd::string_view module_name, nonstd::string_view field_name, Index memory_index, const Limits *page_limits) override {
CHECK_RESULT(m_validator.OnMemory(GetLocation(), *page_limits));
m_externalDelegate->OnImportMemory(import_index, std::string(module_name), std::string(field_name), memory_index, page_limits->initial, page_limits->has_max ? page_limits->max : (page_limits->is_64? WABT_MAX_PAGES64 : WABT_MAX_PAGES32));
m_externalDelegate->OnImportMemory(import_index, std::string(module_name), std::string(field_name), memory_index, page_limits->initial,
page_limits->has_max ? page_limits->max : (page_limits->is_64? (WABT_MAX_PAGES64 - 1) : (WABT_MAX_PAGES32 - 1)));
return Result::Ok;
}
Result OnImportGlobal(Index import_index, nonstd::string_view module_name, nonstd::string_view field_name, Index global_index, Type type, bool mutable_) override {
Expand Down Expand Up @@ -308,7 +309,8 @@ class BinaryReaderDelegateWalrus: public BinaryReaderDelegate {
}
Result OnMemory(Index index, const Limits *limits) override {
CHECK_RESULT(m_validator.OnMemory(GetLocation(), *limits));
m_externalDelegate->OnMemory(index, limits->initial, limits->has_max ? limits->max : (limits->is_64? WABT_MAX_PAGES64 : WABT_MAX_PAGES32));
m_externalDelegate->OnMemory(index, limits->initial,
limits->has_max ? limits->max : (limits->is_64 ? (WABT_MAX_PAGES64 - 1) : (WABT_MAX_PAGES32 - 1)));
return Result::Ok;
}
Result EndMemorySection() override {
Expand Down

0 comments on commit a91d3ce

Please sign in to comment.