Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

wasm2c: support the custom-page-sizes proposal #2508

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ Wabt has been compiled to JavaScript via emscripten. Some of the functionality i
| [multi-memory][] | `--enable-multi-memory` | | ✓ | ✓ | ✓ | ✓ | ✓ |
| [extended-const][] | `--enable-extended-const` | | ✓ | ✓ | ✓ | ✓ | ✓ |
| [relaxed-simd][] | `--enable-relaxed-simd` | | ✓ | ✓ | ✓ | ✓ | |
| [custom-page-sizes][] | `--enable-custom-page-sizes`| | ✓ | ✓ | ✓ | ✓ | |
| [custom-page-sizes][] | `--enable-custom-page-sizes`| | ✓ | ✓ | ✓ | ✓ | |

[exception handling]: https://github.com/WebAssembly/exception-handling
[mutable globals]: https://github.com/WebAssembly/mutable-global
Expand Down
23 changes: 12 additions & 11 deletions src/c-writer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2229,18 +2229,17 @@ void CWriter::WriteDataInitializers() {
Index memory_idx = module_->num_memory_imports;
for (Index i = memory_idx; i < module_->memories.size(); i++) {
const Memory* memory = module_->memories[i];
uint64_t max;
if (memory->page_limits.has_max) {
max = memory->page_limits.max;
} else {
max = memory->page_limits.is_64 ? (static_cast<uint64_t>(1) << 48)
: 65536;
}
const uint64_t max =
memory->page_limits.has_max
? memory->page_limits.max
: WABT_BYTES_TO_MIN_PAGES(
(memory->page_limits.is_64 ? UINT64_MAX : UINT32_MAX),
memory->page_size);
std::string func = GetMemoryAPIString(*memory, "wasm_rt_allocate_memory");
Write(func, "(",
ExternalInstancePtr(ModuleFieldType::Memory, memory->name), ", ",
memory->page_limits.initial, ", ", max, ", ",
memory->page_limits.is_64, ");", Newline());
Write(
func, "(", ExternalInstancePtr(ModuleFieldType::Memory, memory->name),
", ", memory->page_limits.initial, ", ", max, ", ",
memory->page_limits.is_64, ", ", memory->page_size, ");", Newline());
}
}

Expand Down Expand Up @@ -2881,6 +2880,8 @@ void CWriter::WriteImportProperties(CWriterPhase kind) {
write_import_prop(import, "max", "u64",
limits->has_max ? limits->max : default_max);
write_import_prop(import, "is64", "u8", limits->is_64);
write_import_prop(import, "pagesize", "u32",
cast<MemoryImport>(import)->memory.page_size);
} else if (import->kind() == ExternalKind::Table) {
const Limits* limits = &(cast<TableImport>(import)->table.elem_limits);
const uint64_t default_max = std::numeric_limits<uint32_t>::max();
Expand Down
9 changes: 6 additions & 3 deletions src/tools/wasm2c.cc
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,12 @@ static const char s_description[] =
)";

static const std::string supported_features[] = {
"multi-memory", "multi-value", "sign-extension", "saturating-float-to-int",
"exceptions", "memory64", "extended-const", "simd",
"threads", "tail-call"};
"multi-memory", "multi-value",
"sign-extension", "saturating-float-to-int",
"exceptions", "memory64",
"extended-const", "simd",
"threads", "tail-call",
"custom-page-sizes"};

static bool IsFeatureSupported(const std::string& feature) {
return std::find(std::begin(supported_features), std::end(supported_features),
Expand Down
3 changes: 3 additions & 0 deletions test/run-spec-wasm2c.py
Original file line number Diff line number Diff line change
Expand Up @@ -545,6 +545,7 @@ def main(args):
parser.add_argument('--enable-extended-const', action='store_true')
parser.add_argument('--enable-threads', action='store_true')
parser.add_argument('--enable-tail-call', action='store_true')
parser.add_argument('--enable-custom-page-sizes', action='store_true')
parser.add_argument('--disable-bulk-memory', action='store_true')
parser.add_argument('--disable-reference-types', action='store_true')
parser.add_argument('--debug-names', action='store_true')
Expand All @@ -566,6 +567,7 @@ def main(args):
'--enable-extended-const': options.enable_extended_const,
'--enable-threads': options.enable_threads,
'--enable-tail-call': options.enable_tail_call,
'--enable-custom-page-sizes': options.enable_custom_page_sizes,
'--enable-multi-memory': options.enable_multi_memory,
'--disable-bulk-memory': options.disable_bulk_memory,
'--disable-reference-types': options.disable_reference_types,
Expand All @@ -585,6 +587,7 @@ def main(args):
'--enable-extended-const': options.enable_extended_const,
'--enable-threads': options.enable_threads,
'--enable-tail-call': options.enable_tail_call,
'--enable-custom-page-sizes': options.enable_custom_page_sizes,
'--enable-multi-memory': options.enable_multi_memory})

options.cflags += shlex.split(os.environ.get('WASM2C_CFLAGS', ''))
Expand Down
3 changes: 2 additions & 1 deletion test/spec-wasm2c-prefix.c
Original file line number Diff line number Diff line change
Expand Up @@ -403,7 +403,8 @@ static void init_spectest_module(w2c_spectest* instance) {
instance->spectest_global_i64 = 666l;
instance->spectest_global_f32 = 666.6;
instance->spectest_global_f64 = 666.6;
wasm_rt_allocate_memory(&instance->spectest_memory, 1, 2, false);
wasm_rt_allocate_memory(&instance->spectest_memory, 1, 2, false,
WASM_DEFAULT_PAGE_SIZE);
wasm_rt_allocate_funcref_table(&instance->spectest_table, 10, 20);
wasm_rt_allocate_funcref_table(&instance->spectest_table64, 10, 20);
}
Expand Down
2 changes: 2 additions & 0 deletions test/wasm2c/check-imports.txt
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ extern const u32 wasm2c_test_max_env_0x5F_indirect_function_table;
extern const u64 wasm2c_test_min_env_0x5F_linear_memory;
extern const u64 wasm2c_test_max_env_0x5F_linear_memory;
extern const u8 wasm2c_test_is64_env_0x5F_linear_memory;
extern const u32 wasm2c_test_pagesize_env_0x5F_linear_memory;

#ifdef __cplusplus
}
Expand Down Expand Up @@ -857,6 +858,7 @@ const u32 wasm2c_test_max_env_0x5F_indirect_function_table = 4294967295;
const u64 wasm2c_test_min_env_0x5F_linear_memory = 0;
const u64 wasm2c_test_max_env_0x5F_linear_memory = 65536;
const u8 wasm2c_test_is64_env_0x5F_linear_memory = 0;
const u32 wasm2c_test_pagesize_env_0x5F_linear_memory = 65536;

void wasm2c_test_instantiate(w2c_test* instance, struct w2c_env* w2c_env_instance) {
assert(wasm_rt_is_initialized());
Expand Down
2 changes: 2 additions & 0 deletions test/wasm2c/export-names.txt
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ wasm_rt_func_type_t wasm2c_test_get_func_type(uint32_t param_count, uint32_t res
extern const u64 wasm2c_test_min_0x5Cmodule_import0x200x2A0x2F;
extern const u64 wasm2c_test_max_0x5Cmodule_import0x200x2A0x2F;
extern const u8 wasm2c_test_is64_0x5Cmodule_import0x200x2A0x2F;
extern const u32 wasm2c_test_pagesize_0x5Cmodule_import0x200x2A0x2F;

/* export: '' */
void w2c_test_(w2c_test*);
Expand Down Expand Up @@ -905,6 +906,7 @@ static void init_instance_import(w2c_test* instance, struct w2c_0x5Cmodule* w2c_
const u64 wasm2c_test_min_0x5Cmodule_import0x200x2A0x2F = 0;
const u64 wasm2c_test_max_0x5Cmodule_import0x200x2A0x2F = 65536;
const u8 wasm2c_test_is64_0x5Cmodule_import0x200x2A0x2F = 0;
const u32 wasm2c_test_pagesize_0x5Cmodule_import0x200x2A0x2F = 65536;

void wasm2c_test_instantiate(w2c_test* instance, struct w2c_0x5Cmodule* w2c_0x5Cmodule_instance) {
assert(wasm_rt_is_initialized());
Expand Down
2 changes: 1 addition & 1 deletion test/wasm2c/hello.txt
Original file line number Diff line number Diff line change
Expand Up @@ -845,7 +845,7 @@ static const u8 data_segment_data_w2c_test_d0[] = {
};

static void init_memories(w2c_test* instance) {
wasm_rt_allocate_memory(&instance->w2c_memory, 1, 65536, 0);
wasm_rt_allocate_memory(&instance->w2c_memory, 1, 65536, 0, 65536);
LOAD_DATA(instance->w2c_memory, 8u, data_segment_data_w2c_test_d0, 14);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
;;; TOOL: run-spec-wasm2c
;;; ARGS*: --enable-custom-page-sizes --enable-multi-memory
;;; STDIN_FILE: third_party/testsuite/proposals/custom-page-sizes/custom-page-sizes-invalid.wast
(;; STDOUT ;;;
0/0 tests passed.
;;; STDOUT ;;)
6 changes: 6 additions & 0 deletions test/wasm2c/spec/custom-page-sizes/custom-page-sizes.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
;;; TOOL: run-spec-wasm2c
;;; ARGS*: --enable-custom-page-sizes --enable-multi-memory
;;; STDIN_FILE: third_party/testsuite/proposals/custom-page-sizes/custom-page-sizes.wast
(;; STDOUT ;;;
24/24 tests passed.
;;; STDOUT ;;)
29 changes: 17 additions & 12 deletions wasm2c/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -297,13 +297,16 @@ typedef struct {

Next is the definition of a memory instance. The `data` field is a pointer to
`size` bytes of linear memory. The `size` field of `wasm_rt_memory_t` is the
current size of the memory instance in bytes, whereas `pages` is the current
size in pages (65536 bytes.) `max_pages` is the maximum number of pages as
specified by the module, or `0xffffffff` if there is no limit.
current size of the memory instance in bytes, `pages` is the current
size in pages, and `page_size` contains the page size in bytes (65,536 by default).
`max_pages` is the maximum number of pages specified by the module or allowed
by the memory index type (`is64` is true for memories that can grow to 2^64 bytes;
`false` for memories limited to 2^32 bytes).

```c
typedef struct {
uint8_t* data;
uint32_t page_size;
uint64_t pages, max_pages;
uint64_t size;
bool is64;
Expand Down Expand Up @@ -353,10 +356,10 @@ bool wasm_rt_is_initialized(void);
void wasm_rt_free(void);
void wasm_rt_trap(wasm_rt_trap_t) __attribute__((noreturn));
const char* wasm_rt_strerror(wasm_rt_trap_t trap);
void wasm_rt_allocate_memory(wasm_rt_memory_t*, uint32_t initial_pages, uint32_t max_pages, bool is64);
void wasm_rt_allocate_memory(wasm_rt_memory_t*, uint32_t initial_pages, uint32_t max_pages, bool is64, uint32_t page_size);
uint32_t wasm_rt_grow_memory(wasm_rt_memory_t*, uint32_t pages);
void wasm_rt_free_memory(wasm_rt_memory_t*);
void wasm_rt_allocate_memory_shared(wasm_rt_shared_memory_t*, uint32_t initial_pages, uint32_t max_pages, bool is64);
void wasm_rt_allocate_memory_shared(wasm_rt_shared_memory_t*, uint32_t initial_pages, uint32_t max_pages, bool is64, uint32_t page_size);
uint32_t wasm_rt_grow_memory_shared(wasm_rt_shared_memory_t*, uint32_t pages);
void wasm_rt_free_memory_shared(wasm_rt_shared_memory_t*);
void wasm_rt_allocate_funcref_table(wasm_rt_table_t*, uint32_t elements, uint32_t max_elements);
Expand All @@ -381,10 +384,12 @@ with `WASM_RT_TRAP_HANDLER` defined to the name of a trap handler function. The
handler function should be a function taking a `wasm_rt_trap_t` as a parameter
and returning `void`. e.g. `-DWASM_RT_TRAP_HANDLER=my_trap_handler`

`wasm_rt_allocate_memory` initializes a memory instance, and allocates at least
enough space for the given number of initial pages. The memory must be cleared
to zero. The `is64` parameter indicates if the memory is indexed with
an i32 or i64 address.
`wasm_rt_allocate_memory` initializes a memory instance, and allocates
at least enough space for the given number of initial pages, each of
size `page_size` (which must be `WASM_DEFAULT_PAGE_SIZE`, equal to 64
KiB, unless using the custom-page-sizes feature). The memory must be
cleared to zero. The `is64` parameter indicates if the memory is
indexed with an i32 or i64 address.

`wasm_rt_grow_memory` must grow the given memory instance by the given number of
pages. If there isn't enough memory to do so, or the new page count would be
Expand All @@ -399,7 +404,7 @@ arguments and returning `void` . e.g.
`wasm_rt_free_memory` frees the memory instance.

`wasm_rt_allocate_memory_shared` initializes a memory instance that can be
shared by different Wasm threads. It's operation is otherwise similar to
shared by different Wasm threads. Its operation is otherwise similar to
`wasm_rt_allocate_memory`.

`wasm_rt_grow_memory_shared` must grow the given shared memory instance by the
Expand Down Expand Up @@ -658,8 +663,8 @@ int main(int argc, char** argv) {

/* Create two `host` instances to store the memory and current string */
w2c_host host_1, host_2;
wasm_rt_allocate_memory(&host_1.memory, 1, 1, false);
wasm_rt_allocate_memory(&host_2.memory, 1, 1, false);
wasm_rt_allocate_memory(&host_1.memory, 1, 1, false, WASM_DEFAULT_PAGE_SIZE);
wasm_rt_allocate_memory(&host_2.memory, 1, 1, false, WASM_DEFAULT_PAGE_SIZE);

/* Construct the `rot13` module instances */
w2c_rot13 rot13_1, rot13_2;
Expand Down
2 changes: 1 addition & 1 deletion wasm2c/examples/rot13/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ int main(int argc, char** argv) {
/* Create a structure to store the memory and current string, allocating 1
page of Wasm memory (64 KiB) that the rot13 module instance will import. */
struct w2c_host host;
wasm_rt_allocate_memory(&host.memory, 1, 1, false);
wasm_rt_allocate_memory(&host.memory, 1, 1, false, WASM_DEFAULT_PAGE_SIZE);

// Construct an instance of the `rot13` module, which imports from the host.
w2c_rot13 rot13;
Expand Down
29 changes: 19 additions & 10 deletions wasm2c/wasm-rt-mem-impl-helper.inc
Original file line number Diff line number Diff line change
Expand Up @@ -63,21 +63,28 @@

#endif

bool MEMORY_API_NAME(wasm_rt_memory_is_default32)(const MEMORY_TYPE* memory) {
return memory->page_size == WASM_DEFAULT_PAGE_SIZE && !memory->is64;
}

void MEMORY_API_NAME(wasm_rt_allocate_memory)(MEMORY_TYPE* memory,
uint64_t initial_pages,
uint64_t max_pages,
bool is64) {
uint64_t byte_length = initial_pages * WASM_PAGE_SIZE;
bool is64,
uint32_t page_size) {
uint64_t byte_length = initial_pages * page_size;
memory->size = byte_length;
memory->pages = initial_pages;
memory->max_pages = max_pages;
memory->is64 = is64;
memory->page_size = page_size;
MEMORY_LOCK_VAR_INIT(memory->mem_lock);

if (WASM_RT_USE_MMAP && !is64) {
if (WASM_RT_USE_MMAP &&
MEMORY_API_NAME(wasm_rt_memory_is_default32)(memory)) {
#if WASM_RT_USE_MMAP // mmap-related functions don't exist unless this is set
const uint64_t mmap_size =
get_alloc_size_for_mmap(memory->max_pages, memory->is64);
get_alloc_size_for_mmap_default32(memory->max_pages);
void* addr = os_mmap(mmap_size);
if (!addr) {
os_print_last_error("os_mmap failed.");
Expand Down Expand Up @@ -105,11 +112,12 @@ static uint64_t MEMORY_API_NAME(grow_memory_impl)(MEMORY_TYPE* memory,
if (new_pages < old_pages || new_pages > memory->max_pages) {
return (uint64_t)-1;
}
uint64_t old_size = old_pages * WASM_PAGE_SIZE;
uint64_t new_size = new_pages * WASM_PAGE_SIZE;
uint64_t delta_size = delta * WASM_PAGE_SIZE;
uint64_t old_size = old_pages * memory->page_size;
uint64_t new_size = new_pages * memory->page_size;
uint64_t delta_size = delta * memory->page_size;
MEMORY_CELL_TYPE new_data;
if (WASM_RT_USE_MMAP && !memory->is64) {
if (WASM_RT_USE_MMAP &&
MEMORY_API_NAME(wasm_rt_memory_is_default32)(memory)) {
#if WASM_RT_USE_MMAP
new_data = memory->data;
int ret = os_mprotect((void*)(new_data + old_size), delta_size);
Expand Down Expand Up @@ -150,10 +158,11 @@ uint64_t MEMORY_API_NAME(wasm_rt_grow_memory)(MEMORY_TYPE* memory,
}

void MEMORY_API_NAME(wasm_rt_free_memory)(MEMORY_TYPE* memory) {
if (WASM_RT_USE_MMAP && !memory->is64) {
if (WASM_RT_USE_MMAP &&
MEMORY_API_NAME(wasm_rt_memory_is_default32)(memory)) {
#if WASM_RT_USE_MMAP
const uint64_t mmap_size =
get_alloc_size_for_mmap(memory->max_pages, memory->is64);
get_alloc_size_for_mmap_default32(memory->max_pages);
os_munmap((void*)memory->data, mmap_size); // ignore error
#endif
} else {
Expand Down
14 changes: 5 additions & 9 deletions wasm2c/wasm-rt-mem-impl.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,6 @@
#include <sys/mman.h>
#endif

#define WASM_PAGE_SIZE 65536

#ifdef WASM_RT_GROW_FAILED_HANDLER
extern void WASM_RT_GROW_FAILED_HANDLER();
#endif
Expand Down Expand Up @@ -112,7 +110,7 @@ static void os_print_last_error(const char* msg) {
}
}

#else
#else /* !_WIN32 */
static void* os_mmap(size_t size) {
int map_prot = PROT_NONE;
int map_flags = MAP_ANONYMOUS | MAP_PRIVATE;
Expand All @@ -134,17 +132,16 @@ static void os_print_last_error(const char* msg) {
perror(msg);
}

#endif
#endif /* _WIN32 */

static uint64_t get_alloc_size_for_mmap(uint64_t max_pages, bool is64) {
assert(!is64 && "memory64 is not yet compatible with WASM_RT_USE_MMAP");
static uint64_t get_alloc_size_for_mmap_default32(uint64_t max_pages) {
#if WASM_RT_MEMCHECK_GUARD_PAGES
/* Reserve 8GiB. */
const uint64_t max_size = 0x200000000ul;
return max_size;
#else
if (max_pages != 0) {
const uint64_t max_size = max_pages * WASM_PAGE_SIZE;
const uint64_t max_size = max_pages * WASM_DEFAULT_PAGE_SIZE;
return max_size;
}

Expand All @@ -154,7 +151,7 @@ static uint64_t get_alloc_size_for_mmap(uint64_t max_pages, bool is64) {
#endif
}

#endif
#endif /* WASM_RT_USE_MMAP */

// Include operations for memory
#define WASM_RT_MEM_OPS
Expand All @@ -175,4 +172,3 @@ static uint64_t get_alloc_size_for_mmap(uint64_t max_pages, bool is64) {
#undef WIN_MEMORY_LOCK_VAR_INIT
#undef WIN_MEMORY_LOCK_AQUIRE
#undef WIN_MEMORY_LOCK_RELEASE
#undef WASM_PAGE_SIZE
Loading
Loading