diff options
Diffstat (limited to 'third_party/wabt/wasm2c/wasm-rt-impl.c')
-rw-r--r-- | third_party/wabt/wasm2c/wasm-rt-impl.c | 182 |
1 files changed, 182 insertions, 0 deletions
diff --git a/third_party/wabt/wasm2c/wasm-rt-impl.c b/third_party/wabt/wasm2c/wasm-rt-impl.c new file mode 100644 index 000000000..c52063ab3 --- /dev/null +++ b/third_party/wabt/wasm2c/wasm-rt-impl.c @@ -0,0 +1,182 @@ +/* + * Copyright 2018 WebAssembly Community Group participants + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "wasm-rt-impl.h" + +#include <assert.h> +#include <stdarg.h> +#include <stdbool.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#if WASM_RT_MEMCHECK_SIGNAL_HANDLER_POSIX +#include <signal.h> +#include <sys/mman.h> +#include <unistd.h> +#endif + +#define PAGE_SIZE 65536 + +typedef struct FuncType { + wasm_rt_type_t* params; + wasm_rt_type_t* results; + uint32_t param_count; + uint32_t result_count; +} FuncType; + +uint32_t wasm_rt_call_stack_depth; +uint32_t g_saved_call_stack_depth; + +#if WASM_RT_MEMCHECK_SIGNAL_HANDLER +bool g_signal_handler_installed = false; +#endif + +jmp_buf g_jmp_buf; +FuncType* g_func_types; +uint32_t g_func_type_count; + +void wasm_rt_trap(wasm_rt_trap_t code) { + assert(code != WASM_RT_TRAP_NONE); + wasm_rt_call_stack_depth = g_saved_call_stack_depth; + WASM_RT_LONGJMP(g_jmp_buf, code); +} + +static bool func_types_are_equal(FuncType* a, FuncType* b) { + if (a->param_count != b->param_count || a->result_count != b->result_count) + return 0; + int i; + for (i = 0; i < a->param_count; ++i) + if (a->params[i] != b->params[i]) + return 0; + for (i = 0; i < a->result_count; ++i) + if (a->results[i] != b->results[i]) + return 0; + return 1; +} + +uint32_t wasm_rt_register_func_type(uint32_t param_count, + uint32_t result_count, + ...) { + FuncType func_type; + func_type.param_count = param_count; + func_type.params = malloc(param_count * sizeof(wasm_rt_type_t)); + func_type.result_count = result_count; + func_type.results = malloc(result_count * sizeof(wasm_rt_type_t)); + + va_list args; + va_start(args, result_count); + + uint32_t i; + for (i = 0; i < param_count; ++i) + func_type.params[i] = va_arg(args, wasm_rt_type_t); + for (i = 0; i < result_count; ++i) + func_type.results[i] = va_arg(args, wasm_rt_type_t); + va_end(args); + + for (i = 0; i < g_func_type_count; ++i) { + if (func_types_are_equal(&g_func_types[i], &func_type)) { + free(func_type.params); + free(func_type.results); + return i + 1; + } + } + + uint32_t idx = g_func_type_count++; + g_func_types = realloc(g_func_types, g_func_type_count * sizeof(FuncType)); + g_func_types[idx] = func_type; + return idx + 1; +} + +#if WASM_RT_MEMCHECK_SIGNAL_HANDLER_POSIX +static void signal_handler(int sig, siginfo_t* si, void* unused) { + wasm_rt_trap(WASM_RT_TRAP_OOB); +} +#endif + +void wasm_rt_allocate_memory(wasm_rt_memory_t* memory, + uint32_t initial_pages, + uint32_t max_pages) { + uint32_t byte_length = initial_pages * PAGE_SIZE; +#if WASM_RT_MEMCHECK_SIGNAL_HANDLER_POSIX + if (!g_signal_handler_installed) { + g_signal_handler_installed = true; + struct sigaction sa; + sa.sa_flags = SA_SIGINFO; + sigemptyset(&sa.sa_mask); + sa.sa_sigaction = signal_handler; + + /* Install SIGSEGV and SIGBUS handlers, since macOS seems to use SIGBUS. */ + if (sigaction(SIGSEGV, &sa, NULL) != 0 || + sigaction(SIGBUS, &sa, NULL) != 0) { + perror("sigaction failed"); + abort(); + } + } + + /* Reserve 8GiB. */ + void* addr = + mmap(NULL, 0x200000000ul, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (addr == (void*)-1) { + perror("mmap failed"); + abort(); + } + mprotect(addr, byte_length, PROT_READ | PROT_WRITE); + memory->data = addr; +#else + memory->data = calloc(byte_length, 1); +#endif + memory->size = byte_length; + memory->pages = initial_pages; + memory->max_pages = max_pages; +} + +uint32_t wasm_rt_grow_memory(wasm_rt_memory_t* memory, uint32_t delta) { + uint32_t old_pages = memory->pages; + uint32_t new_pages = memory->pages + delta; + if (new_pages == 0) { + return 0; + } + if (new_pages < old_pages || new_pages > memory->max_pages) { + return (uint32_t)-1; + } + uint32_t old_size = old_pages * PAGE_SIZE; + uint32_t new_size = new_pages * PAGE_SIZE; + uint32_t delta_size = delta * PAGE_SIZE; +#if WASM_RT_MEMCHECK_SIGNAL_HANDLER_POSIX + uint8_t* new_data = memory->data; + mprotect(new_data + old_size, delta_size, PROT_READ | PROT_WRITE); +#else + uint8_t* new_data = realloc(memory->data, new_size); + if (new_data == NULL) { + return (uint32_t)-1; + } + memset(new_data + old_size, 0, delta_size); +#endif + memory->pages = new_pages; + memory->size = new_size; + memory->data = new_data; + return old_pages; +} + +void wasm_rt_allocate_table(wasm_rt_table_t* table, + uint32_t elements, + uint32_t max_elements) { + table->size = elements; + table->max_size = max_elements; + table->data = calloc(table->size, sizeof(wasm_rt_elem_t)); +} |