mirror of
https://github.com/bytecodealliance/wasm-micro-runtime.git
synced 2024-11-26 15:32:05 +00:00
Refactor interpreter/AOT module instance layout (#1559)
Refactor the layout of interpreter and AOT module instance: - Unify the interp/AOT module instance, use the same WASMModuleInstance/ WASMMemoryInstance/WASMTableInstance data structures for both interpreter and AOT - Make the offset of most fields the same in module instance for both interpreter and AOT, append memory instance structure, global data and table instances to the end of module instance for interpreter mode (like AOT mode) - For extra fields in WASM module instance, use WASMModuleInstanceExtra to create a field `e` for interpreter - Change the LLVM JIT module instance creating process, LLVM JIT uses the WASM module and module instance same as interpreter/Fast-JIT mode. So that Fast JIT and LLVM JIT can access the same data structures, and make it possible to implement the Multi-tier JIT (tier-up from Fast JIT to LLVM JIT) in the future - Unify some APIs: merge some APIs for module instance and memory instance's related operations (only implement one copy) Note that the AOT ABI is same, the AOT file format, AOT relocation types, how AOT code accesses the AOT module instance and so on are kept unchanged. Refer to: https://github.com/bytecodealliance/wasm-micro-runtime/issues/1384
This commit is contained in:
parent
dc4dcc3d6f
commit
a182926a73
5
.gitignore
vendored
5
.gitignore
vendored
|
@ -28,4 +28,7 @@ tests/wamr-test-suites/workspace
|
|||
|
||||
samples/socket-api/wasm-src/inc/pthread.h
|
||||
|
||||
**/__pycache__
|
||||
**/__pycache__
|
||||
|
||||
# ignore benchmarks generated
|
||||
tests/benchmarks/coremark/coremark*
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
string(TOUPPER ${WAMR_BUILD_TARGET} WAMR_BUILD_TARGET)
|
||||
|
||||
|
||||
# Add definitions for the build target
|
||||
if (WAMR_BUILD_TARGET STREQUAL "X86_64")
|
||||
add_definitions(-DBUILD_TARGET_X86_64)
|
||||
|
@ -85,33 +84,29 @@ endif ()
|
|||
endif ()
|
||||
|
||||
if (WAMR_BUILD_JIT EQUAL 1)
|
||||
if (WAMR_BUILD_AOT EQUAL 1)
|
||||
add_definitions("-DWASM_ENABLE_JIT=1")
|
||||
if (NOT WAMR_BUILD_LAZY_JIT EQUAL 0)
|
||||
# Enable Lazy JIT by default
|
||||
set (WAMR_BUILD_LAZY_JIT 1)
|
||||
add_definitions("-DWASM_ENABLE_LAZY_JIT=1")
|
||||
add_definitions("-DWASM_ENABLE_JIT=1")
|
||||
if (NOT WAMR_BUILD_LAZY_JIT EQUAL 0)
|
||||
# Enable Lazy JIT by default
|
||||
set (WAMR_BUILD_LAZY_JIT 1)
|
||||
add_definitions("-DWASM_ENABLE_LAZY_JIT=1")
|
||||
endif ()
|
||||
if (NOT DEFINED LLVM_DIR)
|
||||
set (LLVM_SRC_ROOT "${WAMR_ROOT_DIR}/core/deps/llvm")
|
||||
set (LLVM_BUILD_ROOT "${LLVM_SRC_ROOT}/build")
|
||||
if (WAMR_BUILD_PLATFORM STREQUAL "windows")
|
||||
set (LLVM_BUILD_ROOT "${LLVM_SRC_ROOT}/win32build")
|
||||
endif ()
|
||||
if (NOT DEFINED LLVM_DIR)
|
||||
set (LLVM_SRC_ROOT "${WAMR_ROOT_DIR}/core/deps/llvm")
|
||||
set (LLVM_BUILD_ROOT "${LLVM_SRC_ROOT}/build")
|
||||
if (WAMR_BUILD_PLATFORM STREQUAL "windows")
|
||||
set (LLVM_BUILD_ROOT "${LLVM_SRC_ROOT}/win32build")
|
||||
endif ()
|
||||
if (NOT EXISTS "${LLVM_BUILD_ROOT}")
|
||||
if (NOT EXISTS "${LLVM_BUILD_ROOT}")
|
||||
message (FATAL_ERROR "Cannot find LLVM dir: ${LLVM_BUILD_ROOT}")
|
||||
endif ()
|
||||
set (CMAKE_PREFIX_PATH "${LLVM_BUILD_ROOT};${CMAKE_PREFIX_PATH}")
|
||||
endif ()
|
||||
find_package(LLVM REQUIRED CONFIG)
|
||||
include_directories(${LLVM_INCLUDE_DIRS})
|
||||
add_definitions(${LLVM_DEFINITIONS})
|
||||
message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}")
|
||||
message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}")
|
||||
else ()
|
||||
set (WAMR_BUILD_JIT 0)
|
||||
message ("-- WAMR JIT disabled due to WAMR AOT is disabled")
|
||||
endif ()
|
||||
set (CMAKE_PREFIX_PATH "${LLVM_BUILD_ROOT};${CMAKE_PREFIX_PATH}")
|
||||
set (LLVM_DIR ${LLVM_BUILD_ROOT}/lib/cmake/llvm)
|
||||
endif ()
|
||||
find_package(LLVM REQUIRED CONFIG)
|
||||
include_directories(${LLVM_INCLUDE_DIRS})
|
||||
add_definitions(${LLVM_DEFINITIONS})
|
||||
message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}")
|
||||
message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}")
|
||||
else ()
|
||||
unset (LLVM_AVAILABLE_LIBS)
|
||||
endif ()
|
||||
|
@ -139,9 +134,6 @@ message (" Build as target ${WAMR_BUILD_TARGET}")
|
|||
message (" CMAKE_BUILD_TYPE " ${CMAKE_BUILD_TYPE})
|
||||
if (WAMR_BUILD_INTERP EQUAL 1)
|
||||
message (" WAMR Interpreter enabled")
|
||||
elseif (WAMR_BUILD_JIT EQUAL 1)
|
||||
set (WAMR_BUILD_INTERP 1)
|
||||
message (" WAMR Interpreter enabled due to WAMR JIT is enabled")
|
||||
else ()
|
||||
message (" WAMR Interpreter disabled")
|
||||
endif ()
|
||||
|
@ -150,16 +142,19 @@ if (WAMR_BUILD_AOT EQUAL 1)
|
|||
else ()
|
||||
message (" WAMR AOT disabled")
|
||||
endif ()
|
||||
if (WAMR_BUILD_FAST_JIT EQUAL 1)
|
||||
message (" WAMR Fast JIT enabled")
|
||||
else ()
|
||||
message (" WAMR Fast JIT disabled")
|
||||
endif ()
|
||||
if (WAMR_BUILD_JIT EQUAL 1)
|
||||
if (WAMR_BUILD_LAZY_JIT EQUAL 1)
|
||||
message (" WAMR LLVM Orc Lazy JIT enabled")
|
||||
else ()
|
||||
message (" WAMR LLVM MC JIT enabled")
|
||||
endif ()
|
||||
elseif (WAMR_BUILD_FAST_JIT EQUAL 1)
|
||||
message (" WAMR Fast JIT enabled")
|
||||
else ()
|
||||
message (" WAMR JIT disabled")
|
||||
message (" WAMR LLVM JIT disabled")
|
||||
endif ()
|
||||
if (WAMR_BUILD_LIBC_BUILTIN EQUAL 1)
|
||||
message (" Libc builtin enabled")
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
# Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
|
||||
if (NOT DEFINED WAMR_ROOT_DIR)
|
||||
set (WAMR_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/../)
|
||||
endif ()
|
||||
|
@ -50,23 +49,28 @@ if (NOT DEFINED WAMR_BUILD_TARGET)
|
|||
endif ()
|
||||
|
||||
################ optional according to settings ################
|
||||
if (WAMR_BUILD_INTERP EQUAL 1 OR WAMR_BUILD_JIT EQUAL 1
|
||||
OR WAMR_BUILD_FAST_JIT EQUAL 1)
|
||||
if (WAMR_BUILD_FAST_JIT EQUAL 1 OR WAMR_BUILD_JIT EQUAL 1)
|
||||
set (WAMR_BUILD_FAST_INTERP 0)
|
||||
endif ()
|
||||
if (WAMR_BUILD_FAST_JIT EQUAL 1 OR WAMR_BUILD_JIT EQUAL 1)
|
||||
# Enable classic interpreter if Fast JIT or LLVM JIT is enabled
|
||||
set (WAMR_BUILD_INTERP 1)
|
||||
set (WAMR_BUILD_FAST_INTERP 0)
|
||||
endif ()
|
||||
|
||||
if (WAMR_BUILD_INTERP EQUAL 1)
|
||||
include (${IWASM_DIR}/interpreter/iwasm_interp.cmake)
|
||||
endif ()
|
||||
|
||||
if (WAMR_BUILD_FAST_JIT EQUAL 1)
|
||||
include (${IWASM_DIR}/fast-jit/iwasm_fast_jit.cmake)
|
||||
endif ()
|
||||
|
||||
if (WAMR_BUILD_JIT EQUAL 1)
|
||||
# Enable AOT if LLVM JIT is enabled
|
||||
set (WAMR_BUILD_AOT 1)
|
||||
include (${IWASM_DIR}/compilation/iwasm_compl.cmake)
|
||||
endif ()
|
||||
|
||||
if (WAMR_BUILD_AOT EQUAL 1)
|
||||
include (${IWASM_DIR}/aot/iwasm_aot.cmake)
|
||||
if (WAMR_BUILD_JIT EQUAL 1)
|
||||
include (${IWASM_DIR}/compilation/iwasm_compl.cmake)
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
if (NOT WAMR_BUILD_JIT EQUAL 1 AND WAMR_BUILD_FAST_JIT EQUAL 1)
|
||||
include (${IWASM_DIR}/fast-jit/iwasm_fast_jit.cmake)
|
||||
endif ()
|
||||
|
||||
if (WAMR_BUILD_APP_FRAMEWORK EQUAL 1)
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
#define _AOT_INTRINSIC_H
|
||||
|
||||
#include "aot_runtime.h"
|
||||
#if WASM_ENABLE_WAMR_COMPILER != 0
|
||||
#if WASM_ENABLE_WAMR_COMPILER != 0 || WASM_ENABLE_JIT != 0
|
||||
#include "aot_llvm.h"
|
||||
#endif
|
||||
|
||||
|
|
|
@ -10,10 +10,6 @@
|
|||
#include "../common/wasm_runtime_common.h"
|
||||
#include "../common/wasm_native.h"
|
||||
#include "../compilation/aot.h"
|
||||
#if WASM_ENABLE_JIT != 0
|
||||
#include "../compilation/aot_llvm.h"
|
||||
#include "../interpreter/wasm_loader.h"
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_DEBUG_AOT != 0
|
||||
#include "debug/elf_parser.h"
|
||||
|
@ -716,23 +712,19 @@ fail:
|
|||
}
|
||||
|
||||
static void
|
||||
destroy_import_memories(AOTImportMemory *import_memories, bool is_jit_mode)
|
||||
destroy_import_memories(AOTImportMemory *import_memories)
|
||||
{
|
||||
if (!is_jit_mode)
|
||||
wasm_runtime_free(import_memories);
|
||||
wasm_runtime_free(import_memories);
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_mem_init_data_list(AOTMemInitData **data_list, uint32 count,
|
||||
bool is_jit_mode)
|
||||
destroy_mem_init_data_list(AOTMemInitData **data_list, uint32 count)
|
||||
{
|
||||
if (!is_jit_mode) {
|
||||
uint32 i;
|
||||
for (i = 0; i < count; i++)
|
||||
if (data_list[i])
|
||||
wasm_runtime_free(data_list[i]);
|
||||
wasm_runtime_free(data_list);
|
||||
}
|
||||
uint32 i;
|
||||
for (i = 0; i < count; i++)
|
||||
if (data_list[i])
|
||||
wasm_runtime_free(data_list[i]);
|
||||
wasm_runtime_free(data_list);
|
||||
}
|
||||
|
||||
static bool
|
||||
|
@ -828,30 +820,25 @@ fail:
|
|||
}
|
||||
|
||||
static void
|
||||
destroy_import_tables(AOTImportTable *import_tables, bool is_jit_mode)
|
||||
destroy_import_tables(AOTImportTable *import_tables)
|
||||
{
|
||||
if (!is_jit_mode)
|
||||
wasm_runtime_free(import_tables);
|
||||
wasm_runtime_free(import_tables);
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_tables(AOTTable *tables, bool is_jit_mode)
|
||||
destroy_tables(AOTTable *tables)
|
||||
{
|
||||
if (!is_jit_mode)
|
||||
wasm_runtime_free(tables);
|
||||
wasm_runtime_free(tables);
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_table_init_data_list(AOTTableInitData **data_list, uint32 count,
|
||||
bool is_jit_mode)
|
||||
destroy_table_init_data_list(AOTTableInitData **data_list, uint32 count)
|
||||
{
|
||||
if (!is_jit_mode) {
|
||||
uint32 i;
|
||||
for (i = 0; i < count; i++)
|
||||
if (data_list[i])
|
||||
wasm_runtime_free(data_list[i]);
|
||||
wasm_runtime_free(data_list);
|
||||
}
|
||||
uint32 i;
|
||||
for (i = 0; i < count; i++)
|
||||
if (data_list[i])
|
||||
wasm_runtime_free(data_list[i]);
|
||||
wasm_runtime_free(data_list);
|
||||
}
|
||||
|
||||
static bool
|
||||
|
@ -1003,15 +990,13 @@ fail:
|
|||
}
|
||||
|
||||
static void
|
||||
destroy_func_types(AOTFuncType **func_types, uint32 count, bool is_jit_mode)
|
||||
destroy_func_types(AOTFuncType **func_types, uint32 count)
|
||||
{
|
||||
if (!is_jit_mode) {
|
||||
uint32 i;
|
||||
for (i = 0; i < count; i++)
|
||||
if (func_types[i])
|
||||
wasm_runtime_free(func_types[i]);
|
||||
wasm_runtime_free(func_types);
|
||||
}
|
||||
uint32 i;
|
||||
for (i = 0; i < count; i++)
|
||||
if (func_types[i])
|
||||
wasm_runtime_free(func_types[i]);
|
||||
wasm_runtime_free(func_types);
|
||||
}
|
||||
|
||||
static bool
|
||||
|
@ -1094,10 +1079,9 @@ fail:
|
|||
}
|
||||
|
||||
static void
|
||||
destroy_import_globals(AOTImportGlobal *import_globals, bool is_jit_mode)
|
||||
destroy_import_globals(AOTImportGlobal *import_globals)
|
||||
{
|
||||
if (!is_jit_mode)
|
||||
wasm_runtime_free(import_globals);
|
||||
wasm_runtime_free(import_globals);
|
||||
}
|
||||
|
||||
static bool
|
||||
|
@ -1177,10 +1161,9 @@ fail:
|
|||
}
|
||||
|
||||
static void
|
||||
destroy_globals(AOTGlobal *globals, bool is_jit_mode)
|
||||
destroy_globals(AOTGlobal *globals)
|
||||
{
|
||||
if (!is_jit_mode)
|
||||
wasm_runtime_free(globals);
|
||||
wasm_runtime_free(globals);
|
||||
}
|
||||
|
||||
static bool
|
||||
|
@ -1259,10 +1242,9 @@ fail:
|
|||
}
|
||||
|
||||
static void
|
||||
destroy_import_funcs(AOTImportFunc *import_funcs, bool is_jit_mode)
|
||||
destroy_import_funcs(AOTImportFunc *import_funcs)
|
||||
{
|
||||
if (!is_jit_mode)
|
||||
wasm_runtime_free(import_funcs);
|
||||
wasm_runtime_free(import_funcs);
|
||||
}
|
||||
|
||||
static bool
|
||||
|
@ -1652,10 +1634,9 @@ fail:
|
|||
}
|
||||
|
||||
static void
|
||||
destroy_exports(AOTExport *exports, bool is_jit_mode)
|
||||
destroy_exports(AOTExport *exports)
|
||||
{
|
||||
if (!is_jit_mode)
|
||||
wasm_runtime_free(exports);
|
||||
wasm_runtime_free(exports);
|
||||
}
|
||||
|
||||
static bool
|
||||
|
@ -2826,427 +2807,46 @@ aot_load_from_aot_file(const uint8 *buf, uint32 size, char *error_buf,
|
|||
return module;
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_JIT != 0
|
||||
#if WASM_ENABLE_LAZY_JIT != 0
|
||||
/* Orc JIT thread arguments */
|
||||
typedef struct OrcJitThreadArg {
|
||||
AOTCompData *comp_data;
|
||||
AOTCompContext *comp_ctx;
|
||||
AOTModule *module;
|
||||
int32 group_idx;
|
||||
int32 group_stride;
|
||||
} OrcJitThreadArg;
|
||||
|
||||
static bool orcjit_stop_compiling = false;
|
||||
static korp_tid orcjit_threads[WASM_LAZY_JIT_COMPILE_THREAD_NUM];
|
||||
static OrcJitThreadArg orcjit_thread_args[WASM_LAZY_JIT_COMPILE_THREAD_NUM];
|
||||
|
||||
static void *
|
||||
orcjit_thread_callback(void *arg)
|
||||
{
|
||||
LLVMErrorRef error;
|
||||
LLVMOrcJITTargetAddress func_addr = 0;
|
||||
OrcJitThreadArg *thread_arg = (OrcJitThreadArg *)arg;
|
||||
AOTCompData *comp_data = thread_arg->comp_data;
|
||||
AOTCompContext *comp_ctx = thread_arg->comp_ctx;
|
||||
AOTModule *module = thread_arg->module;
|
||||
char func_name[32];
|
||||
int32 i;
|
||||
|
||||
/* Compile wasm functions of this group */
|
||||
for (i = thread_arg->group_idx; i < (int32)comp_data->func_count;
|
||||
i += thread_arg->group_stride) {
|
||||
if (!module->func_ptrs[i]) {
|
||||
snprintf(func_name, sizeof(func_name), "%s%d", AOT_FUNC_PREFIX, i);
|
||||
if ((error = LLVMOrcLLJITLookup(comp_ctx->orc_lazyjit, &func_addr,
|
||||
func_name))) {
|
||||
char *err_msg = LLVMGetErrorMessage(error);
|
||||
os_printf("failed to compile orc jit function: %s", err_msg);
|
||||
LLVMDisposeErrorMessage(err_msg);
|
||||
break;
|
||||
}
|
||||
/**
|
||||
* No need to lock the func_ptr[func_idx] here as it is basic
|
||||
* data type, the load/store for it can be finished by one cpu
|
||||
* instruction, and there can be only one cpu instruction
|
||||
* loading/storing at the same time.
|
||||
*/
|
||||
module->func_ptrs[i] = (void *)func_addr;
|
||||
}
|
||||
if (orcjit_stop_compiling) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Try to compile functions that haven't been compiled by other threads */
|
||||
for (i = (int32)comp_data->func_count - 1; i > 0; i--) {
|
||||
if (orcjit_stop_compiling) {
|
||||
break;
|
||||
}
|
||||
if (!module->func_ptrs[i]) {
|
||||
snprintf(func_name, sizeof(func_name), "%s%d", AOT_FUNC_PREFIX, i);
|
||||
if ((error = LLVMOrcLLJITLookup(comp_ctx->orc_lazyjit, &func_addr,
|
||||
func_name))) {
|
||||
char *err_msg = LLVMGetErrorMessage(error);
|
||||
os_printf("failed to compile orc jit function: %s", err_msg);
|
||||
LLVMDisposeErrorMessage(err_msg);
|
||||
break;
|
||||
}
|
||||
module->func_ptrs[i] = (void *)func_addr;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
orcjit_stop_compile_threads()
|
||||
{
|
||||
uint32 i;
|
||||
|
||||
orcjit_stop_compiling = true;
|
||||
for (i = 0; i < WASM_LAZY_JIT_COMPILE_THREAD_NUM; i++) {
|
||||
os_thread_join(orcjit_threads[i], NULL);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static AOTModule *
|
||||
aot_load_from_comp_data(AOTCompData *comp_data, AOTCompContext *comp_ctx,
|
||||
char *error_buf, uint32 error_buf_size)
|
||||
{
|
||||
uint32 i;
|
||||
uint64 size;
|
||||
char func_name[32];
|
||||
AOTModule *module;
|
||||
|
||||
/* Allocate memory for module */
|
||||
if (!(module =
|
||||
loader_malloc(sizeof(AOTModule), error_buf, error_buf_size))) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
module->module_type = Wasm_Module_AoT;
|
||||
|
||||
module->import_memory_count = comp_data->import_memory_count;
|
||||
module->import_memories = comp_data->import_memories;
|
||||
|
||||
module->memory_count = comp_data->memory_count;
|
||||
if (module->memory_count) {
|
||||
size = sizeof(AOTMemory) * (uint64)module->memory_count;
|
||||
if (!(module->memories =
|
||||
loader_malloc(size, error_buf, error_buf_size))) {
|
||||
goto fail1;
|
||||
}
|
||||
|
||||
bh_memcpy_s(module->memories, (uint32)size, comp_data->memories,
|
||||
(uint32)size);
|
||||
}
|
||||
|
||||
module->mem_init_data_list = comp_data->mem_init_data_list;
|
||||
module->mem_init_data_count = comp_data->mem_init_data_count;
|
||||
|
||||
module->import_table_count = comp_data->import_table_count;
|
||||
module->import_tables = comp_data->import_tables;
|
||||
|
||||
module->table_count = comp_data->table_count;
|
||||
module->tables = comp_data->tables;
|
||||
|
||||
module->table_init_data_list = comp_data->table_init_data_list;
|
||||
module->table_init_data_count = comp_data->table_init_data_count;
|
||||
|
||||
module->func_type_count = comp_data->func_type_count;
|
||||
module->func_types = comp_data->func_types;
|
||||
|
||||
module->import_global_count = comp_data->import_global_count;
|
||||
module->import_globals = comp_data->import_globals;
|
||||
|
||||
module->global_count = comp_data->global_count;
|
||||
module->globals = comp_data->globals;
|
||||
|
||||
module->global_count = comp_data->global_count;
|
||||
module->globals = comp_data->globals;
|
||||
|
||||
module->global_data_size = comp_data->global_data_size;
|
||||
|
||||
module->import_func_count = comp_data->import_func_count;
|
||||
module->import_funcs = comp_data->import_funcs;
|
||||
|
||||
module->func_count = comp_data->func_count;
|
||||
|
||||
/* Allocate memory for function pointers */
|
||||
size = (uint64)module->func_count * sizeof(void *);
|
||||
if (size > 0
|
||||
&& !(module->func_ptrs =
|
||||
loader_malloc(size, error_buf, error_buf_size))) {
|
||||
goto fail2;
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_LAZY_JIT != 0
|
||||
/* Create threads to compile the wasm functions */
|
||||
for (i = 0; i < WASM_LAZY_JIT_COMPILE_THREAD_NUM; i++) {
|
||||
orcjit_thread_args[i].comp_data = comp_data;
|
||||
orcjit_thread_args[i].comp_ctx = comp_ctx;
|
||||
orcjit_thread_args[i].module = module;
|
||||
orcjit_thread_args[i].group_idx = (int32)i;
|
||||
orcjit_thread_args[i].group_stride = WASM_LAZY_JIT_COMPILE_THREAD_NUM;
|
||||
if (os_thread_create(&orcjit_threads[i], orcjit_thread_callback,
|
||||
(void *)&orcjit_thread_args[i],
|
||||
APP_THREAD_STACK_SIZE_DEFAULT)
|
||||
!= 0) {
|
||||
uint32 j;
|
||||
|
||||
set_error_buf(error_buf, error_buf_size,
|
||||
"create orcjit compile thread failed");
|
||||
/* Terminate the threads created */
|
||||
orcjit_stop_compiling = true;
|
||||
for (j = 0; j < i; j++) {
|
||||
os_thread_join(orcjit_threads[j], NULL);
|
||||
}
|
||||
goto fail3;
|
||||
}
|
||||
}
|
||||
#else
|
||||
/* Resolve function addresses */
|
||||
bh_assert(comp_ctx->exec_engine);
|
||||
for (i = 0; i < comp_data->func_count; i++) {
|
||||
snprintf(func_name, sizeof(func_name), "%s%d", AOT_FUNC_PREFIX, i);
|
||||
if (!(module->func_ptrs[i] = (void *)LLVMGetFunctionAddress(
|
||||
comp_ctx->exec_engine, func_name))) {
|
||||
set_error_buf(error_buf, error_buf_size,
|
||||
"get function address failed");
|
||||
goto fail3;
|
||||
}
|
||||
}
|
||||
#endif /* WASM_ENABLE_LAZY_JIT != 0 */
|
||||
|
||||
/* Allocation memory for function type indexes */
|
||||
size = (uint64)module->func_count * sizeof(uint32);
|
||||
if (size > 0
|
||||
&& !(module->func_type_indexes =
|
||||
loader_malloc(size, error_buf, error_buf_size))) {
|
||||
goto fail4;
|
||||
}
|
||||
for (i = 0; i < comp_data->func_count; i++)
|
||||
module->func_type_indexes[i] = comp_data->funcs[i]->func_type_index;
|
||||
|
||||
module->export_count = comp_data->wasm_module->export_count;
|
||||
module->exports = comp_data->wasm_module->exports;
|
||||
|
||||
module->start_func_index = comp_data->start_func_index;
|
||||
if (comp_data->start_func_index != (uint32)-1) {
|
||||
bh_assert(comp_data->start_func_index
|
||||
< module->import_func_count + module->func_count);
|
||||
/* TODO: fix issue that start func cannot be import func */
|
||||
if (comp_data->start_func_index >= module->import_func_count) {
|
||||
#if WASM_ENABLE_LAZY_JIT != 0
|
||||
if (!module->func_ptrs[comp_data->start_func_index
|
||||
- module->import_func_count]) {
|
||||
LLVMErrorRef error;
|
||||
LLVMOrcJITTargetAddress func_addr = 0;
|
||||
|
||||
snprintf(func_name, sizeof(func_name), "%s%d", AOT_FUNC_PREFIX,
|
||||
comp_data->start_func_index
|
||||
- module->import_func_count);
|
||||
if ((error = LLVMOrcLLJITLookup(comp_ctx->orc_lazyjit,
|
||||
&func_addr, func_name))) {
|
||||
char *err_msg = LLVMGetErrorMessage(error);
|
||||
set_error_buf_v(error_buf, error_buf_size,
|
||||
"failed to compile orc jit function: %s",
|
||||
err_msg);
|
||||
LLVMDisposeErrorMessage(err_msg);
|
||||
goto fail5;
|
||||
}
|
||||
module->func_ptrs[comp_data->start_func_index
|
||||
- module->import_func_count] =
|
||||
(void *)func_addr;
|
||||
}
|
||||
#endif
|
||||
module->start_function =
|
||||
module->func_ptrs[comp_data->start_func_index
|
||||
- module->import_func_count];
|
||||
}
|
||||
}
|
||||
|
||||
module->malloc_func_index = comp_data->malloc_func_index;
|
||||
module->free_func_index = comp_data->free_func_index;
|
||||
module->retain_func_index = comp_data->retain_func_index;
|
||||
|
||||
module->aux_data_end_global_index = comp_data->aux_data_end_global_index;
|
||||
module->aux_data_end = comp_data->aux_data_end;
|
||||
module->aux_heap_base_global_index = comp_data->aux_heap_base_global_index;
|
||||
module->aux_heap_base = comp_data->aux_heap_base;
|
||||
module->aux_stack_top_global_index = comp_data->aux_stack_top_global_index;
|
||||
module->aux_stack_bottom = comp_data->aux_stack_bottom;
|
||||
module->aux_stack_size = comp_data->aux_stack_size;
|
||||
|
||||
module->code = NULL;
|
||||
module->code_size = 0;
|
||||
|
||||
module->is_jit_mode = true;
|
||||
|
||||
module->wasm_module = comp_data->wasm_module;
|
||||
module->comp_ctx = comp_ctx;
|
||||
module->comp_data = comp_data;
|
||||
|
||||
#if WASM_ENABLE_LIBC_WASI != 0
|
||||
module->import_wasi_api = comp_data->wasm_module->import_wasi_api;
|
||||
#endif
|
||||
|
||||
return module;
|
||||
|
||||
#if WASM_ENABLE_LAZY_JIT != 0
|
||||
fail5:
|
||||
if (module->func_type_indexes)
|
||||
wasm_runtime_free(module->func_type_indexes);
|
||||
#endif
|
||||
|
||||
fail4:
|
||||
#if WASM_ENABLE_LAZY_JIT != 0
|
||||
/* Terminate all threads before free module->func_ptrs */
|
||||
orcjit_stop_compile_threads();
|
||||
#endif
|
||||
fail3:
|
||||
if (module->func_ptrs)
|
||||
wasm_runtime_free(module->func_ptrs);
|
||||
fail2:
|
||||
if (module->memory_count > 0)
|
||||
wasm_runtime_free(module->memories);
|
||||
fail1:
|
||||
wasm_runtime_free(module);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
AOTModule *
|
||||
aot_convert_wasm_module(WASMModule *wasm_module, char *error_buf,
|
||||
uint32 error_buf_size)
|
||||
{
|
||||
AOTCompData *comp_data;
|
||||
AOTCompContext *comp_ctx;
|
||||
AOTModule *aot_module;
|
||||
AOTCompOption option = { 0 };
|
||||
char *aot_last_error;
|
||||
|
||||
comp_data = aot_create_comp_data(wasm_module);
|
||||
if (!comp_data) {
|
||||
aot_last_error = aot_get_last_error();
|
||||
bh_assert(aot_last_error != NULL);
|
||||
set_error_buf(error_buf, error_buf_size, aot_last_error);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
option.is_jit_mode = true;
|
||||
option.opt_level = 3;
|
||||
option.size_level = 3;
|
||||
#if WASM_ENABLE_BULK_MEMORY != 0
|
||||
option.enable_bulk_memory = true;
|
||||
#endif
|
||||
#if WASM_ENABLE_THREAD_MGR != 0
|
||||
option.enable_thread_mgr = true;
|
||||
#endif
|
||||
#if WASM_ENABLE_TAIL_CALL != 0
|
||||
option.enable_tail_call = true;
|
||||
#endif
|
||||
#if WASM_ENABLE_SIMD != 0
|
||||
option.enable_simd = true;
|
||||
#endif
|
||||
#if WASM_ENABLE_REF_TYPES != 0
|
||||
option.enable_ref_types = true;
|
||||
#endif
|
||||
option.enable_aux_stack_check = true;
|
||||
#if (WASM_ENABLE_PERF_PROFILING != 0) || (WASM_ENABLE_DUMP_CALL_STACK != 0)
|
||||
option.enable_aux_stack_frame = true;
|
||||
#endif
|
||||
|
||||
comp_ctx = aot_create_comp_context(comp_data, &option);
|
||||
if (!comp_ctx) {
|
||||
aot_last_error = aot_get_last_error();
|
||||
bh_assert(aot_last_error != NULL);
|
||||
set_error_buf(error_buf, error_buf_size, aot_last_error);
|
||||
goto fail1;
|
||||
}
|
||||
|
||||
if (!aot_compile_wasm(comp_ctx)) {
|
||||
aot_last_error = aot_get_last_error();
|
||||
bh_assert(aot_last_error != NULL);
|
||||
set_error_buf(error_buf, error_buf_size, aot_last_error);
|
||||
goto fail2;
|
||||
}
|
||||
|
||||
aot_module =
|
||||
aot_load_from_comp_data(comp_data, comp_ctx, error_buf, error_buf_size);
|
||||
if (!aot_module) {
|
||||
goto fail2;
|
||||
}
|
||||
|
||||
return aot_module;
|
||||
|
||||
fail2:
|
||||
aot_destroy_comp_context(comp_ctx);
|
||||
fail1:
|
||||
aot_destroy_comp_data(comp_data);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
aot_unload(AOTModule *module)
|
||||
{
|
||||
#if WASM_ENABLE_JIT != 0
|
||||
#if WASM_ENABLE_LAZY_JIT != 0
|
||||
orcjit_stop_compile_threads();
|
||||
#endif
|
||||
|
||||
if (module->comp_data)
|
||||
aot_destroy_comp_data(module->comp_data);
|
||||
|
||||
if (module->comp_ctx)
|
||||
aot_destroy_comp_context(module->comp_ctx);
|
||||
|
||||
if (module->wasm_module)
|
||||
wasm_loader_unload(module->wasm_module);
|
||||
#endif
|
||||
|
||||
if (module->import_memories)
|
||||
destroy_import_memories(module->import_memories, module->is_jit_mode);
|
||||
destroy_import_memories(module->import_memories);
|
||||
|
||||
if (module->memories)
|
||||
wasm_runtime_free(module->memories);
|
||||
|
||||
if (module->mem_init_data_list)
|
||||
destroy_mem_init_data_list(module->mem_init_data_list,
|
||||
module->mem_init_data_count,
|
||||
module->is_jit_mode);
|
||||
module->mem_init_data_count);
|
||||
|
||||
if (module->native_symbol_list)
|
||||
wasm_runtime_free(module->native_symbol_list);
|
||||
|
||||
if (module->import_tables)
|
||||
destroy_import_tables(module->import_tables, module->is_jit_mode);
|
||||
destroy_import_tables(module->import_tables);
|
||||
|
||||
if (module->tables)
|
||||
destroy_tables(module->tables, module->is_jit_mode);
|
||||
destroy_tables(module->tables);
|
||||
|
||||
if (module->table_init_data_list)
|
||||
destroy_table_init_data_list(module->table_init_data_list,
|
||||
module->table_init_data_count,
|
||||
module->is_jit_mode);
|
||||
module->table_init_data_count);
|
||||
|
||||
if (module->func_types)
|
||||
destroy_func_types(module->func_types, module->func_type_count,
|
||||
module->is_jit_mode);
|
||||
destroy_func_types(module->func_types, module->func_type_count);
|
||||
|
||||
if (module->import_globals)
|
||||
destroy_import_globals(module->import_globals, module->is_jit_mode);
|
||||
destroy_import_globals(module->import_globals);
|
||||
|
||||
if (module->globals)
|
||||
destroy_globals(module->globals, module->is_jit_mode);
|
||||
destroy_globals(module->globals);
|
||||
|
||||
if (module->import_funcs)
|
||||
destroy_import_funcs(module->import_funcs, module->is_jit_mode);
|
||||
destroy_import_funcs(module->import_funcs);
|
||||
|
||||
if (module->exports)
|
||||
destroy_exports(module->exports, module->is_jit_mode);
|
||||
destroy_exports(module->exports);
|
||||
|
||||
if (module->func_type_indexes)
|
||||
wasm_runtime_free(module->func_type_indexes);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -10,34 +10,11 @@
|
|||
#include "../common/wasm_runtime_common.h"
|
||||
#include "../interpreter/wasm_runtime.h"
|
||||
#include "../compilation/aot.h"
|
||||
#if WASM_ENABLE_JIT != 0
|
||||
#include "../compilation/aot_llvm.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum AOTExceptionID {
|
||||
EXCE_UNREACHABLE = 0,
|
||||
EXCE_OUT_OF_MEMORY,
|
||||
EXCE_OUT_OF_BOUNDS_MEMORY_ACCESS,
|
||||
EXCE_INTEGER_OVERFLOW,
|
||||
EXCE_INTEGER_DIVIDE_BY_ZERO,
|
||||
EXCE_INVALID_CONVERSION_TO_INTEGER,
|
||||
EXCE_INVALID_FUNCTION_TYPE_INDEX,
|
||||
EXCE_INVALID_FUNCTION_INDEX,
|
||||
EXCE_UNDEFINED_ELEMENT,
|
||||
EXCE_UNINITIALIZED_ELEMENT,
|
||||
EXCE_CALL_UNLINKED_IMPORT_FUNC,
|
||||
EXCE_NATIVE_STACK_OVERFLOW,
|
||||
EXCE_UNALIGNED_ATOMIC,
|
||||
EXCE_AUX_STACK_OVERFLOW,
|
||||
EXCE_AUX_STACK_UNDERFLOW,
|
||||
EXCE_OUT_OF_BOUNDS_TABLE_ACCESS,
|
||||
EXCE_NUM,
|
||||
} AOTExceptionID;
|
||||
|
||||
typedef enum AOTSectionType {
|
||||
AOT_SECTION_TYPE_TARGET_INFO = 0,
|
||||
AOT_SECTION_TYPE_INIT_DATA = 1,
|
||||
|
@ -171,7 +148,7 @@ typedef struct AOTModule {
|
|||
|
||||
/* function info */
|
||||
uint32 func_count;
|
||||
/* point to AOTed/JITed functions */
|
||||
/* point to AOTed functions */
|
||||
void **func_ptrs;
|
||||
/* function type indexes */
|
||||
uint32 *func_type_indexes;
|
||||
|
@ -182,24 +159,24 @@ typedef struct AOTModule {
|
|||
|
||||
/* start function index, -1 denotes no start function */
|
||||
uint32 start_func_index;
|
||||
/* start function, point to AOTed/JITed function */
|
||||
/* start function, point to AOTed function */
|
||||
void *start_function;
|
||||
|
||||
uint32 malloc_func_index;
|
||||
uint32 free_func_index;
|
||||
uint32 retain_func_index;
|
||||
|
||||
/* AOTed code, NULL for JIT mode */
|
||||
/* AOTed code */
|
||||
void *code;
|
||||
uint32 code_size;
|
||||
|
||||
/* literal for AOTed code, NULL for JIT mode */
|
||||
/* literal for AOTed code */
|
||||
uint8 *literal;
|
||||
uint32 literal_size;
|
||||
|
||||
#if defined(BH_PLATFORM_WINDOWS)
|
||||
/* extra plt data area for __ymm, __xmm and __real constants
|
||||
in Windows platform, NULL for JIT mode */
|
||||
in Windows platform */
|
||||
uint8 *extra_plt_data;
|
||||
uint32 extra_plt_data_size;
|
||||
uint32 ymm_plt_count;
|
||||
|
@ -217,7 +194,7 @@ typedef struct AOTModule {
|
|||
#endif
|
||||
|
||||
/* data sections in AOT object file, including .data, .rodata
|
||||
* and .rodata.cstN. NULL for JIT mode. */
|
||||
and .rodata.cstN. */
|
||||
AOTObjectDataSection *data_sections;
|
||||
uint32 data_section_count;
|
||||
|
||||
|
@ -244,18 +221,9 @@ typedef struct AOTModule {
|
|||
/* auxiliary stack size resolved */
|
||||
uint32 aux_stack_size;
|
||||
|
||||
/* is jit mode or not */
|
||||
bool is_jit_mode;
|
||||
|
||||
/* is indirect mode or not */
|
||||
bool is_indirect_mode;
|
||||
|
||||
#if WASM_ENABLE_JIT != 0
|
||||
WASMModule *wasm_module;
|
||||
AOTCompContext *comp_ctx;
|
||||
AOTCompData *comp_data;
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_LIBC_WASI != 0
|
||||
WASIArguments wasi_args;
|
||||
bool import_wasi_api;
|
||||
|
@ -274,130 +242,9 @@ typedef struct AOTModule {
|
|||
#endif
|
||||
} AOTModule;
|
||||
|
||||
typedef union {
|
||||
uint64 _make_it_8_bytes_;
|
||||
void *ptr;
|
||||
} AOTPointer;
|
||||
|
||||
typedef union {
|
||||
uint64 u64;
|
||||
uint32 u32[2];
|
||||
} MemBound;
|
||||
|
||||
typedef struct AOTMemoryInstance {
|
||||
uint32 module_type;
|
||||
/* shared memory flag */
|
||||
bool is_shared;
|
||||
|
||||
/* memory space info */
|
||||
uint32 num_bytes_per_page;
|
||||
uint32 cur_page_count;
|
||||
uint32 max_page_count;
|
||||
uint32 memory_data_size;
|
||||
AOTPointer memory_data;
|
||||
AOTPointer memory_data_end;
|
||||
|
||||
/* heap space info */
|
||||
AOTPointer heap_data;
|
||||
AOTPointer heap_data_end;
|
||||
AOTPointer heap_handle;
|
||||
|
||||
/* boundary check constants for aot code */
|
||||
MemBound mem_bound_check_1byte;
|
||||
MemBound mem_bound_check_2bytes;
|
||||
MemBound mem_bound_check_4bytes;
|
||||
MemBound mem_bound_check_8bytes;
|
||||
MemBound mem_bound_check_16bytes;
|
||||
} AOTMemoryInstance;
|
||||
|
||||
typedef struct AOTTableInstance {
|
||||
uint32 cur_size;
|
||||
/*
|
||||
* only grow in the range of [:max_size)
|
||||
* if the table is growable, max_size equals to its declared maximum size
|
||||
* otherwise, max_size equals to its declared minimum size
|
||||
*/
|
||||
uint32 max_size;
|
||||
/*
|
||||
* +------------------------------+ <--- data
|
||||
* | ref.func[] or ref.extern[]
|
||||
* +------------------------------+
|
||||
*/
|
||||
uint32 data[1];
|
||||
} AOTTableInstance;
|
||||
|
||||
typedef struct AOTModuleInstance {
|
||||
uint32 module_type;
|
||||
|
||||
/* memories */
|
||||
uint32 memory_count;
|
||||
AOTPointer memories;
|
||||
|
||||
/* global and table info */
|
||||
uint32 global_data_size;
|
||||
/*
|
||||
* the count of AOTTableInstance.
|
||||
* it includes imported tables and local tables.
|
||||
*
|
||||
* TODO: for now we treate imported table like a local table
|
||||
*/
|
||||
uint32 table_count;
|
||||
/* points to global_data */
|
||||
AOTPointer global_data;
|
||||
/* points to AOTTableInstance[] */
|
||||
AOTPointer tables;
|
||||
|
||||
/* function pointer array */
|
||||
AOTPointer func_ptrs;
|
||||
/* function type indexes */
|
||||
AOTPointer func_type_indexes;
|
||||
|
||||
/* export info */
|
||||
uint32 export_func_count;
|
||||
uint32 export_global_count;
|
||||
uint32 export_mem_count;
|
||||
uint32 export_tab_count;
|
||||
AOTPointer export_funcs;
|
||||
AOTPointer export_globals;
|
||||
AOTPointer export_memories;
|
||||
AOTPointer export_tables;
|
||||
|
||||
/* The exception buffer for current thread. */
|
||||
char cur_exception[128];
|
||||
/* The custom data that can be set/get by
|
||||
* wasm_runtime_set_custom_data/wasm_runtime_get_custom_data */
|
||||
AOTPointer custom_data;
|
||||
/* The AOT module */
|
||||
AOTPointer aot_module;
|
||||
/* WASI context */
|
||||
AOTPointer wasi_ctx;
|
||||
/* function performance profiling info list */
|
||||
AOTPointer func_perf_profilings;
|
||||
/* stack frames, used in call stack dump and perf profiling */
|
||||
AOTPointer frames;
|
||||
|
||||
AOTPointer exec_env_singleton;
|
||||
|
||||
uint32 default_wasm_stack_size;
|
||||
|
||||
/* reserved */
|
||||
uint32 reserved[9];
|
||||
|
||||
/*
|
||||
* +------------------------------+ <-- memories.ptr
|
||||
* | #0 AOTMemoryInstance
|
||||
* +------------------------------+ <-- global_data.ptr
|
||||
* | global data
|
||||
* +------------------------------+ <-- tables.ptr
|
||||
* | AOTTableInstance[table_count]
|
||||
* +------------------------------+
|
||||
*/
|
||||
union {
|
||||
uint64 _make_it_8_byte_aligned_;
|
||||
AOTMemoryInstance memory_instances[1];
|
||||
uint8 bytes[1];
|
||||
} global_table_data;
|
||||
} AOTModuleInstance;
|
||||
#define AOTMemoryInstance WASMMemoryInstance
|
||||
#define AOTTableInstance WASMTableInstance
|
||||
#define AOTModuleInstance WASMModuleInstance
|
||||
|
||||
/* Target info, read from ELF header of object file */
|
||||
typedef struct AOTTargetInfo {
|
||||
|
@ -462,21 +309,6 @@ AOTModule *
|
|||
aot_load_from_sections(AOTSection *section_list, char *error_buf,
|
||||
uint32 error_buf_size);
|
||||
|
||||
#if WASM_ENABLE_JIT != 0
|
||||
/**
|
||||
* Convert WASM module to AOT module
|
||||
*
|
||||
* @param wasm_module the WASM module to convert
|
||||
* @param error_buf output of the error info
|
||||
* @param error_buf_size the size of the error string
|
||||
*
|
||||
* @return return AOT module loaded, NULL if failed
|
||||
*/
|
||||
AOTModule *
|
||||
aot_convert_wasm_module(WASMModule *wasm_module, char *error_buf,
|
||||
uint32 error_buf_size);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Unload a AOT module.
|
||||
*
|
||||
|
@ -549,9 +381,6 @@ aot_create_exec_env_and_call_function(AOTModuleInstance *module_inst,
|
|||
AOTFunctionInstance *function,
|
||||
unsigned argc, uint32 argv[]);
|
||||
|
||||
bool
|
||||
aot_create_exec_env_singleton(AOTModuleInstance *module_inst);
|
||||
|
||||
/**
|
||||
* Set AOT module instance exception with exception string
|
||||
*
|
||||
|
@ -575,14 +404,6 @@ aot_set_exception_with_id(AOTModuleInstance *module_inst, uint32 id);
|
|||
const char *
|
||||
aot_get_exception(AOTModuleInstance *module_inst);
|
||||
|
||||
/**
|
||||
* Clear exception info of the AOT module instance.
|
||||
*
|
||||
* @param module_inst the AOT module instance
|
||||
*/
|
||||
void
|
||||
aot_clear_exception(AOTModuleInstance *module_inst);
|
||||
|
||||
uint32
|
||||
aot_module_malloc(AOTModuleInstance *module_inst, uint32 size,
|
||||
void **p_native_addr);
|
||||
|
@ -598,29 +419,6 @@ uint32
|
|||
aot_module_dup_data(AOTModuleInstance *module_inst, const char *src,
|
||||
uint32 size);
|
||||
|
||||
bool
|
||||
aot_validate_app_addr(AOTModuleInstance *module_inst, uint32 app_offset,
|
||||
uint32 size);
|
||||
|
||||
bool
|
||||
aot_validate_native_addr(AOTModuleInstance *module_inst, void *native_ptr,
|
||||
uint32 size);
|
||||
|
||||
void *
|
||||
aot_addr_app_to_native(AOTModuleInstance *module_inst, uint32 app_offset);
|
||||
|
||||
uint32
|
||||
aot_addr_native_to_app(AOTModuleInstance *module_inst, void *native_ptr);
|
||||
|
||||
bool
|
||||
aot_get_app_addr_range(AOTModuleInstance *module_inst, uint32 app_offset,
|
||||
uint32 *p_app_start_offset, uint32 *p_app_end_offset);
|
||||
|
||||
bool
|
||||
aot_get_native_addr_range(AOTModuleInstance *module_inst, uint8 *native_ptr,
|
||||
uint8 **p_native_start_addr,
|
||||
uint8 **p_native_end_addr);
|
||||
|
||||
bool
|
||||
aot_enlarge_memory(AOTModuleInstance *module_inst, uint32 inc_page_count);
|
||||
|
||||
|
@ -635,6 +433,10 @@ bool
|
|||
aot_call_indirect(WASMExecEnv *exec_env, uint32 tbl_idx, uint32 table_elem_idx,
|
||||
uint32 argc, uint32 *argv);
|
||||
|
||||
/**
|
||||
* Check whether the app address and the buf is inside the linear memory,
|
||||
* and convert the app address into native address
|
||||
*/
|
||||
bool
|
||||
aot_check_app_addr_and_convert(AOTModuleInstance *module_inst, bool is_str,
|
||||
uint32 app_buf_addr, uint32 app_buf_size,
|
||||
|
@ -666,16 +468,6 @@ bool
|
|||
aot_get_aux_stack(WASMExecEnv *exec_env, uint32 *start_offset, uint32 *size);
|
||||
#endif
|
||||
|
||||
#ifdef OS_ENABLE_HW_BOUND_CHECK
|
||||
#ifndef BH_PLATFORM_WINDOWS
|
||||
void
|
||||
aot_signal_handler(WASMSignalInfo *sig_info);
|
||||
#else
|
||||
LONG
|
||||
aot_exception_handler(WASMSignalInfo *sig_info);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void
|
||||
aot_get_module_mem_consumption(const AOTModule *module,
|
||||
WASMModuleMemConsumption *mem_conspn);
|
||||
|
@ -707,9 +499,6 @@ aot_table_grow(AOTModuleInstance *module_inst, uint32 tbl_idx,
|
|||
uint32 inc_entries, uint32 init_val);
|
||||
#endif
|
||||
|
||||
AOTTableInstance *
|
||||
aot_next_tbl_inst(const AOTTableInstance *tbl_inst);
|
||||
|
||||
bool
|
||||
aot_alloc_frame(WASMExecEnv *exec_env, uint32 func_index);
|
||||
|
||||
|
|
|
@ -2,16 +2,20 @@
|
|||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#include "wasm_c_api_internal.h"
|
||||
|
||||
#include "bh_assert.h"
|
||||
#include "wasm_memory.h"
|
||||
#include "wasm_runtime_common.h"
|
||||
#if WASM_ENABLE_INTERP != 0
|
||||
#include "wasm_runtime.h"
|
||||
#endif
|
||||
#if WASM_ENABLE_AOT != 0
|
||||
#include "aot_runtime.h"
|
||||
#endif
|
||||
#if WASM_ENABLE_JIT != 0 && WASM_ENABLE_LAZY_JIT == 0
|
||||
#include "aot.h"
|
||||
#include "aot_llvm.h"
|
||||
#endif /*WASM_ENABLE_JIT != 0 && WASM_ENABLE_LAZY_JIT == 0*/
|
||||
#endif /*WASM_ENABLE_AOT != 0*/
|
||||
|
||||
#define ASSERT_NOT_IMPLEMENTED() bh_assert(!"not implemented")
|
||||
#define UNREACHABLE() bh_assert(!"unreachable")
|
||||
|
@ -302,9 +306,11 @@ wasm_engine_new_internal(mem_alloc_type_t type, const MemAllocOption *opts)
|
|||
goto failed;
|
||||
}
|
||||
|
||||
#if BH_DEBUG != 0
|
||||
#ifndef NDEBUG
|
||||
/*DEBUG*/
|
||||
bh_log_set_verbose_level(5);
|
||||
#else
|
||||
/*VERBOSE*/
|
||||
bh_log_set_verbose_level(3);
|
||||
#endif
|
||||
|
||||
|
@ -1655,7 +1661,7 @@ wasm_trap_new_internal(WASMModuleInstanceCommon *inst_comm_rt,
|
|||
|
||||
#if WASM_ENABLE_AOT != 0
|
||||
if (inst_comm_rt->module_type == Wasm_Module_AoT) {
|
||||
trap->frames = ((AOTModuleInstance *)inst_comm_rt)->frames.ptr;
|
||||
trap->frames = ((AOTModuleInstance *)inst_comm_rt)->frames;
|
||||
}
|
||||
#endif
|
||||
#endif /* WASM_ENABLE_DUMP_CALL_STACK != 0 */
|
||||
|
@ -2379,6 +2385,61 @@ failed_exporttype_new:
|
|||
wasm_exporttype_vec_delete(out);
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_JIT == 0 || WASM_ENABLE_LAZY_JIT != 0
|
||||
void
|
||||
wasm_module_serialize(wasm_module_t *module, own wasm_byte_vec_t *out)
|
||||
{
|
||||
(void)module;
|
||||
(void)out;
|
||||
LOG_ERROR("only supported serialization in JIT with eager compilation");
|
||||
}
|
||||
|
||||
own wasm_module_t *
|
||||
wasm_module_deserialize(wasm_store_t *module, const wasm_byte_vec_t *binary)
|
||||
{
|
||||
(void)module;
|
||||
(void)binary;
|
||||
LOG_ERROR("only supported deserialization in JIT with eager compilation");
|
||||
return NULL;
|
||||
}
|
||||
#else
|
||||
|
||||
extern uint8 *
|
||||
aot_emit_aot_file_buf(AOTCompContext *comp_ctx, AOTCompData *comp_data,
|
||||
uint32 *p_aot_file_size);
|
||||
void
|
||||
wasm_module_serialize(wasm_module_t *module, own wasm_byte_vec_t *out)
|
||||
{
|
||||
wasm_module_ex_t *module_ex;
|
||||
AOTCompContext *comp_ctx;
|
||||
AOTCompData *comp_data;
|
||||
uint8 *aot_file_buf = NULL;
|
||||
uint32 aot_file_size = 0;
|
||||
|
||||
if (!module || !out)
|
||||
return;
|
||||
|
||||
module_ex = module_to_module_ext(module);
|
||||
comp_ctx = ((WASMModule *)(module_ex->module_comm_rt))->comp_ctx;
|
||||
comp_data = ((WASMModule *)(module_ex->module_comm_rt))->comp_data;
|
||||
bh_assert(comp_ctx != NULL && comp_data != NULL);
|
||||
|
||||
aot_file_buf = aot_emit_aot_file_buf(comp_ctx, comp_data, &aot_file_size);
|
||||
if (!aot_file_buf)
|
||||
return;
|
||||
|
||||
wasm_byte_vec_new(out, aot_file_size, (wasm_byte_t *)aot_file_buf);
|
||||
wasm_runtime_free(aot_file_buf);
|
||||
return;
|
||||
}
|
||||
|
||||
own wasm_module_t *
|
||||
wasm_module_deserialize(wasm_store_t *store, const wasm_byte_vec_t *binary)
|
||||
{
|
||||
return wasm_module_new(store, binary);
|
||||
}
|
||||
#endif
|
||||
|
||||
static wasm_func_t *
|
||||
wasm_func_new_basic(wasm_store_t *store, const wasm_functype_t *type,
|
||||
wasm_func_callback_t func_callback)
|
||||
|
@ -2482,9 +2543,9 @@ wasm_func_new_internal(wasm_store_t *store, uint16 func_idx_rt,
|
|||
#if WASM_ENABLE_INTERP != 0
|
||||
if (inst_comm_rt->module_type == Wasm_Module_Bytecode) {
|
||||
bh_assert(func_idx_rt
|
||||
< ((WASMModuleInstance *)inst_comm_rt)->function_count);
|
||||
< ((WASMModuleInstance *)inst_comm_rt)->e->function_count);
|
||||
WASMFunctionInstance *func_interp =
|
||||
((WASMModuleInstance *)inst_comm_rt)->functions + func_idx_rt;
|
||||
((WASMModuleInstance *)inst_comm_rt)->e->functions + func_idx_rt;
|
||||
type_rt = func_interp->is_import_func
|
||||
? func_interp->u.func_import->func_type
|
||||
: func_interp->u.func->func_type;
|
||||
|
@ -2496,7 +2557,7 @@ wasm_func_new_internal(wasm_store_t *store, uint16 func_idx_rt,
|
|||
/* use same index to trace the function type in AOTFuncType **func_types
|
||||
*/
|
||||
AOTModule *module_aot =
|
||||
((AOTModuleInstance *)inst_comm_rt)->aot_module.ptr;
|
||||
(AOTModule *)((AOTModuleInstance *)inst_comm_rt)->module;
|
||||
if (func_idx_rt < module_aot->import_func_count) {
|
||||
type_rt = (module_aot->import_funcs + func_idx_rt)->func_type;
|
||||
}
|
||||
|
@ -2605,6 +2666,7 @@ params_to_argv(const wasm_val_vec_t *params,
|
|||
}
|
||||
|
||||
if (!params || !params->num_elems || !params->size || !params->data) {
|
||||
LOG_ERROR("the parameter params is invalid");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -2662,6 +2724,7 @@ argv_to_results(const uint32 *argv, const wasm_valtype_vec_t *result_defs,
|
|||
}
|
||||
|
||||
if (!results || !results->size || !results->data) {
|
||||
LOG_ERROR("the parameter results is invalid");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -2748,7 +2811,7 @@ wasm_func_call(const wasm_func_t *func, const wasm_val_vec_t *params,
|
|||
|
||||
#if WASM_ENABLE_INTERP != 0
|
||||
if (func->inst_comm_rt->module_type == Wasm_Module_Bytecode) {
|
||||
func_comm_rt = ((WASMModuleInstance *)func->inst_comm_rt)->functions
|
||||
func_comm_rt = ((WASMModuleInstance *)func->inst_comm_rt)->e->functions
|
||||
+ func->func_idx_rt;
|
||||
}
|
||||
#endif
|
||||
|
@ -2758,7 +2821,7 @@ wasm_func_call(const wasm_func_t *func, const wasm_val_vec_t *params,
|
|||
if (!(func_comm_rt = func->func_comm_rt)) {
|
||||
AOTModuleInstance *inst_aot =
|
||||
(AOTModuleInstance *)func->inst_comm_rt;
|
||||
AOTModule *module_aot = (AOTModule *)inst_aot->aot_module.ptr;
|
||||
AOTModule *module_aot = (AOTModule *)inst_aot->module;
|
||||
uint32 export_i = 0, export_func_j = 0;
|
||||
|
||||
for (; export_i < module_aot->export_count; ++export_i) {
|
||||
|
@ -2766,7 +2829,7 @@ wasm_func_call(const wasm_func_t *func, const wasm_val_vec_t *params,
|
|||
if (export->kind == EXPORT_KIND_FUNC) {
|
||||
if (export->index == func->func_idx_rt) {
|
||||
func_comm_rt =
|
||||
(AOTFunctionInstance *)inst_aot->export_funcs.ptr
|
||||
(AOTFunctionInstance *)inst_aot->export_functions
|
||||
+ export_func_j;
|
||||
((wasm_func_t *)func)->func_comm_rt = func_comm_rt;
|
||||
break;
|
||||
|
@ -2788,6 +2851,7 @@ wasm_func_call(const wasm_func_t *func, const wasm_val_vec_t *params,
|
|||
|
||||
param_count = wasm_func_param_arity(func);
|
||||
result_count = wasm_func_result_arity(func);
|
||||
|
||||
alloc_count = (param_count > result_count) ? param_count : result_count;
|
||||
if (alloc_count > (size_t)sizeof(argv_buf) / sizeof(uint64)) {
|
||||
if (!(argv = malloc_internal(sizeof(uint64) * alloc_count))) {
|
||||
|
@ -2968,7 +3032,7 @@ interp_global_set(const WASMModuleInstance *inst_interp, uint16 global_idx_rt,
|
|||
const wasm_val_t *v)
|
||||
{
|
||||
const WASMGlobalInstance *global_interp =
|
||||
inst_interp->globals + global_idx_rt;
|
||||
inst_interp->e->globals + global_idx_rt;
|
||||
uint8 val_type_rt = global_interp->type;
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
uint8 *data = global_interp->import_global_inst
|
||||
|
@ -2987,7 +3051,7 @@ static bool
|
|||
interp_global_get(const WASMModuleInstance *inst_interp, uint16 global_idx_rt,
|
||||
wasm_val_t *out)
|
||||
{
|
||||
WASMGlobalInstance *global_interp = inst_interp->globals + global_idx_rt;
|
||||
WASMGlobalInstance *global_interp = inst_interp->e->globals + global_idx_rt;
|
||||
uint8 val_type_rt = global_interp->type;
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
uint8 *data = global_interp->import_global_inst
|
||||
|
@ -3007,7 +3071,7 @@ static bool
|
|||
aot_global_set(const AOTModuleInstance *inst_aot, uint16 global_idx_rt,
|
||||
const wasm_val_t *v)
|
||||
{
|
||||
AOTModule *module_aot = inst_aot->aot_module.ptr;
|
||||
AOTModule *module_aot = (AOTModule *)inst_aot->module;
|
||||
uint8 val_type_rt = 0;
|
||||
uint32 data_offset = 0;
|
||||
void *data = NULL;
|
||||
|
@ -3025,7 +3089,7 @@ aot_global_set(const AOTModuleInstance *inst_aot, uint16 global_idx_rt,
|
|||
.type;
|
||||
}
|
||||
|
||||
data = (void *)((uint8 *)inst_aot->global_data.ptr + data_offset);
|
||||
data = (void *)(inst_aot->global_data + data_offset);
|
||||
return wasm_val_to_rt_val((WASMModuleInstanceCommon *)inst_aot, val_type_rt,
|
||||
v, data);
|
||||
}
|
||||
|
@ -3034,7 +3098,7 @@ static bool
|
|||
aot_global_get(const AOTModuleInstance *inst_aot, uint16 global_idx_rt,
|
||||
wasm_val_t *out)
|
||||
{
|
||||
AOTModule *module_aot = inst_aot->aot_module.ptr;
|
||||
AOTModule *module_aot = (AOTModule *)inst_aot->module;
|
||||
uint8 val_type_rt = 0;
|
||||
uint32 data_offset = 0;
|
||||
uint8 *data = NULL;
|
||||
|
@ -3052,7 +3116,7 @@ aot_global_get(const AOTModuleInstance *inst_aot, uint16 global_idx_rt,
|
|||
.type;
|
||||
}
|
||||
|
||||
data = (uint8 *)inst_aot->global_data.ptr + data_offset;
|
||||
data = inst_aot->global_data + data_offset;
|
||||
return rt_val_to_wasm_val(data, val_type_rt, out);
|
||||
}
|
||||
#endif
|
||||
|
@ -3149,7 +3213,7 @@ wasm_global_new_internal(wasm_store_t *store, uint16 global_idx_rt,
|
|||
#if WASM_ENABLE_INTERP != 0
|
||||
if (inst_comm_rt->module_type == Wasm_Module_Bytecode) {
|
||||
WASMGlobalInstance *global_interp =
|
||||
((WASMModuleInstance *)inst_comm_rt)->globals + global_idx_rt;
|
||||
((WASMModuleInstance *)inst_comm_rt)->e->globals + global_idx_rt;
|
||||
val_type_rt = global_interp->type;
|
||||
is_mutable = global_interp->is_mutable;
|
||||
init = true;
|
||||
|
@ -3159,7 +3223,7 @@ wasm_global_new_internal(wasm_store_t *store, uint16 global_idx_rt,
|
|||
#if WASM_ENABLE_AOT != 0
|
||||
if (inst_comm_rt->module_type == Wasm_Module_AoT) {
|
||||
AOTModuleInstance *inst_aot = (AOTModuleInstance *)inst_comm_rt;
|
||||
AOTModule *module_aot = inst_aot->aot_module.ptr;
|
||||
AOTModule *module_aot = (AOTModule *)inst_aot->module;
|
||||
|
||||
init = true;
|
||||
|
||||
|
@ -3257,7 +3321,6 @@ wasm_table_new_internal(wasm_store_t *store, uint16 table_idx_rt,
|
|||
wasm_table_t *table = NULL;
|
||||
uint8 val_type_rt = 0;
|
||||
uint32 init_size = 0, max_size = 0;
|
||||
bool init_flag = false;
|
||||
|
||||
bh_assert(singleton_engine);
|
||||
|
||||
|
@ -3272,46 +3335,12 @@ wasm_table_new_internal(wasm_store_t *store, uint16 table_idx_rt,
|
|||
table->store = store;
|
||||
table->kind = WASM_EXTERN_TABLE;
|
||||
|
||||
#if WASM_ENABLE_INTERP != 0
|
||||
if (inst_comm_rt->module_type == Wasm_Module_Bytecode) {
|
||||
WASMTableInstance *table_interp =
|
||||
((WASMModuleInstance *)inst_comm_rt)->tables[table_idx_rt];
|
||||
val_type_rt = table_interp->elem_type;
|
||||
init_size = table_interp->cur_size;
|
||||
max_size = table_interp->max_size;
|
||||
init_flag = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_AOT != 0
|
||||
if (inst_comm_rt->module_type == Wasm_Module_AoT) {
|
||||
AOTModuleInstance *inst_aot = (AOTModuleInstance *)inst_comm_rt;
|
||||
AOTModule *module_aot = (AOTModule *)inst_aot->aot_module.ptr;
|
||||
|
||||
if (table_idx_rt < module_aot->import_table_count) {
|
||||
AOTImportTable *table_aot =
|
||||
module_aot->import_tables + table_idx_rt;
|
||||
val_type_rt = table_aot->elem_type;
|
||||
init_size = table_aot->table_init_size;
|
||||
max_size = table_aot->table_max_size;
|
||||
}
|
||||
else {
|
||||
AOTTable *table_aot =
|
||||
module_aot->tables
|
||||
+ (table_idx_rt - module_aot->import_table_count);
|
||||
val_type_rt = table_aot->elem_type;
|
||||
init_size = table_aot->table_init_size;
|
||||
max_size = table_aot->table_max_size;
|
||||
}
|
||||
init_flag = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* a wrong combination of module filetype and compilation flags
|
||||
* leads to below branch
|
||||
*/
|
||||
if (!init_flag) {
|
||||
if (!wasm_runtime_get_table_inst_elem_type(
|
||||
inst_comm_rt, table_idx_rt, &val_type_rt, &init_size, &max_size)) {
|
||||
/*
|
||||
* a wrong combination of module filetype and compilation flags
|
||||
* leads to below branch
|
||||
*/
|
||||
goto failed;
|
||||
}
|
||||
|
||||
|
@ -3400,19 +3429,18 @@ wasm_table_get(const wasm_table_t *table, wasm_table_size_t index)
|
|||
if (index >= table_interp->cur_size) {
|
||||
return NULL;
|
||||
}
|
||||
ref_idx = ((uint32 *)table_interp->base_addr)[index];
|
||||
ref_idx = table_interp->elems[index];
|
||||
}
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_AOT != 0
|
||||
if (table->inst_comm_rt->module_type == Wasm_Module_AoT) {
|
||||
AOTModuleInstance *inst_aot = (AOTModuleInstance *)table->inst_comm_rt;
|
||||
AOTTableInstance *table_aot =
|
||||
(AOTTableInstance *)inst_aot->tables.ptr + table->table_idx_rt;
|
||||
AOTTableInstance *table_aot = inst_aot->tables[table->table_idx_rt];
|
||||
if (index >= table_aot->cur_size) {
|
||||
return NULL;
|
||||
}
|
||||
ref_idx = table_aot->data[index];
|
||||
ref_idx = table_aot->elems[index];
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -3472,24 +3500,23 @@ wasm_table_set(wasm_table_t *table, wasm_table_size_t index,
|
|||
return false;
|
||||
}
|
||||
|
||||
p_ref_idx = ((uint32 *)table_interp->base_addr) + index;
|
||||
p_ref_idx = table_interp->elems + index;
|
||||
function_count =
|
||||
((WASMModuleInstance *)table->inst_comm_rt)->function_count;
|
||||
((WASMModuleInstance *)table->inst_comm_rt)->e->function_count;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_AOT != 0
|
||||
if (table->inst_comm_rt->module_type == Wasm_Module_AoT) {
|
||||
AOTModuleInstance *inst_aot = (AOTModuleInstance *)table->inst_comm_rt;
|
||||
AOTModule *module_aot = (AOTModule *)inst_aot->aot_module.ptr;
|
||||
AOTTableInstance *table_aot =
|
||||
(AOTTableInstance *)inst_aot->tables.ptr + table->table_idx_rt;
|
||||
AOTModule *module_aot = (AOTModule *)inst_aot->module;
|
||||
AOTTableInstance *table_aot = inst_aot->tables[table->table_idx_rt];
|
||||
|
||||
if (index >= table_aot->cur_size) {
|
||||
return false;
|
||||
}
|
||||
|
||||
p_ref_idx = table_aot->data + index;
|
||||
p_ref_idx = table_aot->elems + index;
|
||||
function_count = module_aot->func_count;
|
||||
}
|
||||
#endif
|
||||
|
@ -3545,7 +3572,7 @@ wasm_table_size(const wasm_table_t *table)
|
|||
#if WASM_ENABLE_AOT != 0
|
||||
if (table->inst_comm_rt->module_type == Wasm_Module_AoT) {
|
||||
AOTModuleInstance *inst_aot = (AOTModuleInstance *)table->inst_comm_rt;
|
||||
AOTModule *module_aot = (AOTModule *)inst_aot->aot_module.ptr;
|
||||
AOTModule *module_aot = (AOTModule *)inst_aot->module;
|
||||
|
||||
if (table->table_idx_rt < module_aot->import_table_count) {
|
||||
AOTImportTable *table_aot =
|
||||
|
@ -3660,7 +3687,7 @@ wasm_memory_new_internal(wasm_store_t *store, uint16 memory_idx_rt,
|
|||
#if WASM_ENABLE_AOT != 0
|
||||
if (inst_comm_rt->module_type == Wasm_Module_AoT) {
|
||||
AOTModuleInstance *inst_aot = (AOTModuleInstance *)inst_comm_rt;
|
||||
AOTModule *module_aot = (AOTModule *)(inst_aot->aot_module.ptr);
|
||||
AOTModule *module_aot = (AOTModule *)inst_aot->module;
|
||||
|
||||
if (memory_idx_rt < module_aot->import_memory_count) {
|
||||
min_pages = module_aot->import_memories->mem_init_page_count;
|
||||
|
@ -3744,8 +3771,8 @@ wasm_memory_data(wasm_memory_t *memory)
|
|||
AOTModuleInstance *module_inst = (AOTModuleInstance *)module_inst_comm;
|
||||
AOTMemoryInstance *memory_inst =
|
||||
((AOTMemoryInstance **)
|
||||
module_inst->memories.ptr)[memory->memory_idx_rt];
|
||||
return (byte_t *)memory_inst->memory_data.ptr;
|
||||
module_inst->memories)[memory->memory_idx_rt];
|
||||
return (byte_t *)memory_inst->memory_data;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -3781,7 +3808,7 @@ wasm_memory_data_size(const wasm_memory_t *memory)
|
|||
AOTModuleInstance *module_inst = (AOTModuleInstance *)module_inst_comm;
|
||||
AOTMemoryInstance *memory_inst =
|
||||
((AOTMemoryInstance **)
|
||||
module_inst->memories.ptr)[memory->memory_idx_rt];
|
||||
module_inst->memories)[memory->memory_idx_rt];
|
||||
return memory_inst->cur_page_count * memory_inst->num_bytes_per_page;
|
||||
}
|
||||
#endif
|
||||
|
@ -3818,7 +3845,7 @@ wasm_memory_size(const wasm_memory_t *memory)
|
|||
AOTModuleInstance *module_inst = (AOTModuleInstance *)module_inst_comm;
|
||||
AOTMemoryInstance *memory_inst =
|
||||
((AOTMemoryInstance **)
|
||||
module_inst->memories.ptr)[memory->memory_idx_rt];
|
||||
module_inst->memories)[memory->memory_idx_rt];
|
||||
return memory_inst->cur_page_count;
|
||||
}
|
||||
#endif
|
||||
|
@ -4197,7 +4224,7 @@ aot_process_export(wasm_store_t *store, const AOTModuleInstance *inst_aot,
|
|||
|
||||
bh_assert(store && inst_aot && externals);
|
||||
|
||||
module_aot = (AOTModule *)inst_aot->aot_module.ptr;
|
||||
module_aot = (AOTModule *)inst_aot->module;
|
||||
bh_assert(module_aot);
|
||||
|
||||
for (i = 0; i < module_aot->export_count; ++i) {
|
||||
|
@ -4420,8 +4447,9 @@ wasm_instance_new_with_args(wasm_store_t *store, const wasm_module_t *module,
|
|||
uint32 export_cnt =
|
||||
((AOTModuleInstance *)instance->inst_comm_rt)->export_func_count
|
||||
+ ((AOTModuleInstance *)instance->inst_comm_rt)->export_global_count
|
||||
+ ((AOTModuleInstance *)instance->inst_comm_rt)->export_tab_count
|
||||
+ ((AOTModuleInstance *)instance->inst_comm_rt)->export_mem_count;
|
||||
+ ((AOTModuleInstance *)instance->inst_comm_rt)->export_table_count
|
||||
+ ((AOTModuleInstance *)instance->inst_comm_rt)
|
||||
->export_memory_count;
|
||||
|
||||
INIT_VEC(instance->exports, wasm_extern_vec_new_uninitialized,
|
||||
export_cnt);
|
||||
|
|
|
@ -65,7 +65,7 @@ wasm_exec_env_create_internal(struct WASMModuleInstanceCommon *module_inst,
|
|||
#if WASM_ENABLE_AOT != 0
|
||||
if (module_inst->module_type == Wasm_Module_AoT) {
|
||||
AOTModuleInstance *i = (AOTModuleInstance *)module_inst;
|
||||
AOTModule *m = (AOTModule *)i->aot_module.ptr;
|
||||
AOTModule *m = (AOTModule *)i->module;
|
||||
exec_env->native_symbol = m->native_symbol_list;
|
||||
}
|
||||
#endif
|
||||
|
@ -135,7 +135,7 @@ wasm_exec_env_create(struct WASMModuleInstanceCommon *module_inst,
|
|||
/* Set the aux_stack_boundary and aux_stack_bottom */
|
||||
if (module_inst->module_type == Wasm_Module_AoT) {
|
||||
AOTModule *module =
|
||||
(AOTModule *)(((AOTModuleInstance *)module_inst)->aot_module.ptr);
|
||||
(AOTModule *)((AOTModuleInstance *)module_inst)->module;
|
||||
exec_env->aux_stack_bottom.bottom = module->aux_stack_bottom;
|
||||
exec_env->aux_stack_boundary.boundary =
|
||||
module->aux_stack_bottom - module->aux_stack_size;
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
*/
|
||||
|
||||
#include "wasm_runtime_common.h"
|
||||
#include "../interpreter/wasm_runtime.h"
|
||||
#include "bh_platform.h"
|
||||
#include "mem_alloc.h"
|
||||
|
||||
|
@ -138,6 +139,9 @@ wasm_runtime_free_internal(void *ptr)
|
|||
{
|
||||
if (!ptr) {
|
||||
LOG_WARNING("warning: wasm_runtime_free with NULL pointer\n");
|
||||
#if BH_ENABLE_GC_VERIFY != 0
|
||||
exit(-1);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -160,6 +164,9 @@ wasm_runtime_malloc(unsigned int size)
|
|||
LOG_WARNING("warning: wasm_runtime_malloc with size zero\n");
|
||||
/* At lease alloc 1 byte to avoid malloc failed */
|
||||
size = 1;
|
||||
#if BH_ENABLE_GC_VERIFY != 0
|
||||
exit(-1);
|
||||
#endif
|
||||
}
|
||||
|
||||
return wasm_runtime_malloc_internal(size);
|
||||
|
@ -185,3 +192,446 @@ wasm_runtime_get_mem_alloc_info(mem_alloc_info_t *mem_alloc_info)
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
wasm_runtime_validate_app_addr(WASMModuleInstanceCommon *module_inst_comm,
|
||||
uint32 app_offset, uint32 size)
|
||||
{
|
||||
WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm;
|
||||
WASMMemoryInstance *memory_inst;
|
||||
|
||||
bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
|
||||
|| module_inst_comm->module_type == Wasm_Module_AoT);
|
||||
|
||||
memory_inst = wasm_get_default_memory(module_inst);
|
||||
if (!memory_inst) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* integer overflow check */
|
||||
if (app_offset > UINT32_MAX - size) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (app_offset + size <= memory_inst->memory_data_size) {
|
||||
return true;
|
||||
}
|
||||
|
||||
fail:
|
||||
wasm_set_exception(module_inst, "out of bounds memory access");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
wasm_runtime_validate_app_str_addr(WASMModuleInstanceCommon *module_inst_comm,
|
||||
uint32 app_str_offset)
|
||||
{
|
||||
WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm;
|
||||
uint32 app_end_offset;
|
||||
char *str, *str_end;
|
||||
|
||||
bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
|
||||
|| module_inst_comm->module_type == Wasm_Module_AoT);
|
||||
|
||||
if (!wasm_runtime_get_app_addr_range(module_inst_comm, app_str_offset, NULL,
|
||||
&app_end_offset))
|
||||
goto fail;
|
||||
|
||||
str = wasm_runtime_addr_app_to_native(module_inst_comm, app_str_offset);
|
||||
str_end = str + (app_end_offset - app_str_offset);
|
||||
while (str < str_end && *str != '\0')
|
||||
str++;
|
||||
if (str == str_end)
|
||||
goto fail;
|
||||
|
||||
return true;
|
||||
fail:
|
||||
wasm_set_exception(module_inst, "out of bounds memory access");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
wasm_runtime_validate_native_addr(WASMModuleInstanceCommon *module_inst_comm,
|
||||
void *native_ptr, uint32 size)
|
||||
{
|
||||
WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm;
|
||||
WASMMemoryInstance *memory_inst;
|
||||
uint8 *addr = (uint8 *)native_ptr;
|
||||
|
||||
bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
|
||||
|| module_inst_comm->module_type == Wasm_Module_AoT);
|
||||
|
||||
memory_inst = wasm_get_default_memory(module_inst);
|
||||
if (!memory_inst) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* integer overflow check */
|
||||
if ((uintptr_t)addr > UINTPTR_MAX - size) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (memory_inst->memory_data <= addr
|
||||
&& addr + size <= memory_inst->memory_data_end) {
|
||||
return true;
|
||||
}
|
||||
|
||||
fail:
|
||||
wasm_set_exception(module_inst, "out of bounds memory access");
|
||||
return false;
|
||||
}
|
||||
|
||||
void *
|
||||
wasm_runtime_addr_app_to_native(WASMModuleInstanceCommon *module_inst_comm,
|
||||
uint32 app_offset)
|
||||
{
|
||||
WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm;
|
||||
WASMMemoryInstance *memory_inst;
|
||||
uint8 *addr;
|
||||
|
||||
bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
|
||||
|| module_inst_comm->module_type == Wasm_Module_AoT);
|
||||
|
||||
memory_inst = wasm_get_default_memory(module_inst);
|
||||
if (!memory_inst) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
addr = memory_inst->memory_data + app_offset;
|
||||
|
||||
if (memory_inst->memory_data <= addr && addr < memory_inst->memory_data_end)
|
||||
return addr;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint32
|
||||
wasm_runtime_addr_native_to_app(WASMModuleInstanceCommon *module_inst_comm,
|
||||
void *native_ptr)
|
||||
{
|
||||
WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm;
|
||||
WASMMemoryInstance *memory_inst;
|
||||
uint8 *addr = (uint8 *)native_ptr;
|
||||
|
||||
bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
|
||||
|| module_inst_comm->module_type == Wasm_Module_AoT);
|
||||
|
||||
memory_inst = wasm_get_default_memory(module_inst);
|
||||
if (!memory_inst) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (memory_inst->memory_data <= addr && addr < memory_inst->memory_data_end)
|
||||
return (uint32)(addr - memory_inst->memory_data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool
|
||||
wasm_runtime_get_app_addr_range(WASMModuleInstanceCommon *module_inst_comm,
|
||||
uint32 app_offset, uint32 *p_app_start_offset,
|
||||
uint32 *p_app_end_offset)
|
||||
{
|
||||
WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm;
|
||||
WASMMemoryInstance *memory_inst;
|
||||
uint32 memory_data_size;
|
||||
|
||||
bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
|
||||
|| module_inst_comm->module_type == Wasm_Module_AoT);
|
||||
|
||||
memory_inst = wasm_get_default_memory(module_inst);
|
||||
if (!memory_inst) {
|
||||
return false;
|
||||
}
|
||||
|
||||
memory_data_size = memory_inst->memory_data_size;
|
||||
|
||||
if (app_offset < memory_data_size) {
|
||||
if (p_app_start_offset)
|
||||
*p_app_start_offset = 0;
|
||||
if (p_app_end_offset)
|
||||
*p_app_end_offset = memory_data_size;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
wasm_runtime_get_native_addr_range(WASMModuleInstanceCommon *module_inst_comm,
|
||||
uint8 *native_ptr,
|
||||
uint8 **p_native_start_addr,
|
||||
uint8 **p_native_end_addr)
|
||||
{
|
||||
WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm;
|
||||
WASMMemoryInstance *memory_inst;
|
||||
uint8 *addr = (uint8 *)native_ptr;
|
||||
|
||||
bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
|
||||
|| module_inst_comm->module_type == Wasm_Module_AoT);
|
||||
|
||||
memory_inst = wasm_get_default_memory(module_inst);
|
||||
if (!memory_inst) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (memory_inst->memory_data <= addr
|
||||
&& addr < memory_inst->memory_data_end) {
|
||||
if (p_native_start_addr)
|
||||
*p_native_start_addr = memory_inst->memory_data;
|
||||
if (p_native_end_addr)
|
||||
*p_native_end_addr = memory_inst->memory_data_end;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
wasm_check_app_addr_and_convert(WASMModuleInstance *module_inst, bool is_str,
|
||||
uint32 app_buf_addr, uint32 app_buf_size,
|
||||
void **p_native_addr)
|
||||
{
|
||||
WASMMemoryInstance *memory_inst = wasm_get_default_memory(module_inst);
|
||||
uint8 *native_addr;
|
||||
|
||||
if (!memory_inst) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
native_addr = memory_inst->memory_data + app_buf_addr;
|
||||
|
||||
/* No need to check the app_offset and buf_size if memory access
|
||||
boundary check with hardware trap is enabled */
|
||||
#ifndef OS_ENABLE_HW_BOUND_CHECK
|
||||
if (app_buf_addr >= memory_inst->memory_data_size) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!is_str) {
|
||||
if (app_buf_size > memory_inst->memory_data_size - app_buf_addr) {
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
else {
|
||||
const char *str, *str_end;
|
||||
|
||||
/* The whole string must be in the linear memory */
|
||||
str = (const char *)native_addr;
|
||||
str_end = (const char *)memory_inst->memory_data_end;
|
||||
while (str < str_end && *str != '\0')
|
||||
str++;
|
||||
if (str == str_end)
|
||||
goto fail;
|
||||
}
|
||||
#endif
|
||||
|
||||
*p_native_addr = (void *)native_addr;
|
||||
return true;
|
||||
fail:
|
||||
wasm_set_exception(module_inst, "out of bounds memory access");
|
||||
return false;
|
||||
}
|
||||
|
||||
WASMMemoryInstance *
|
||||
wasm_get_default_memory(WASMModuleInstance *module_inst)
|
||||
{
|
||||
if (module_inst->memories)
|
||||
return module_inst->memories[0];
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifndef OS_ENABLE_HW_BOUND_CHECK
|
||||
bool
|
||||
wasm_enlarge_memory(WASMModuleInstance *module, uint32 inc_page_count)
|
||||
{
|
||||
WASMMemoryInstance *memory = wasm_get_default_memory(module);
|
||||
uint8 *memory_data_old, *memory_data_new, *heap_data_old;
|
||||
uint32 num_bytes_per_page, heap_size, total_size_old;
|
||||
uint32 cur_page_count, max_page_count, total_page_count;
|
||||
uint64 total_size_new;
|
||||
bool ret = true;
|
||||
|
||||
if (!memory)
|
||||
return false;
|
||||
|
||||
heap_data_old = memory->heap_data;
|
||||
heap_size = (uint32)(memory->heap_data_end - memory->heap_data);
|
||||
|
||||
memory_data_old = memory->memory_data;
|
||||
total_size_old = memory->memory_data_size;
|
||||
|
||||
num_bytes_per_page = memory->num_bytes_per_page;
|
||||
cur_page_count = memory->cur_page_count;
|
||||
max_page_count = memory->max_page_count;
|
||||
total_page_count = inc_page_count + cur_page_count;
|
||||
total_size_new = num_bytes_per_page * (uint64)total_page_count;
|
||||
|
||||
if (inc_page_count <= 0)
|
||||
/* No need to enlarge memory */
|
||||
return true;
|
||||
|
||||
if (total_page_count < cur_page_count /* integer overflow */
|
||||
|| total_page_count > max_page_count) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bh_assert(total_size_new <= 4 * (uint64)BH_GB);
|
||||
if (total_size_new > UINT32_MAX) {
|
||||
/* Resize to 1 page with size 4G-1 */
|
||||
num_bytes_per_page = UINT32_MAX;
|
||||
total_page_count = max_page_count = 1;
|
||||
total_size_new = UINT32_MAX;
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_SHARED_MEMORY != 0
|
||||
if (memory->is_shared) {
|
||||
memory->num_bytes_per_page = num_bytes_per_page;
|
||||
memory->cur_page_count = total_page_count;
|
||||
memory->max_page_count = max_page_count;
|
||||
/* No need to update memory->memory_data_size as it is
|
||||
initialized with the maximum memory data size for
|
||||
shared memory */
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (heap_size > 0) {
|
||||
if (mem_allocator_is_heap_corrupted(memory->heap_handle)) {
|
||||
wasm_runtime_show_app_heap_corrupted_prompt();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(memory_data_new =
|
||||
wasm_runtime_realloc(memory_data_old, (uint32)total_size_new))) {
|
||||
if (!(memory_data_new = wasm_runtime_malloc((uint32)total_size_new))) {
|
||||
return false;
|
||||
}
|
||||
if (memory_data_old) {
|
||||
bh_memcpy_s(memory_data_new, (uint32)total_size_new,
|
||||
memory_data_old, total_size_old);
|
||||
wasm_runtime_free(memory_data_old);
|
||||
}
|
||||
}
|
||||
|
||||
memset(memory_data_new + total_size_old, 0,
|
||||
(uint32)total_size_new - total_size_old);
|
||||
|
||||
if (heap_size > 0) {
|
||||
if (mem_allocator_migrate(memory->heap_handle,
|
||||
(char *)heap_data_old
|
||||
+ (memory_data_new - memory_data_old),
|
||||
heap_size)
|
||||
!= 0) {
|
||||
/* Don't return here as memory->memory_data is obsolete and
|
||||
must be updated to be correctly used later. */
|
||||
ret = false;
|
||||
}
|
||||
}
|
||||
|
||||
memory->heap_data = memory_data_new + (heap_data_old - memory_data_old);
|
||||
memory->heap_data_end = memory->heap_data + heap_size;
|
||||
|
||||
memory->num_bytes_per_page = num_bytes_per_page;
|
||||
memory->cur_page_count = total_page_count;
|
||||
memory->max_page_count = max_page_count;
|
||||
memory->memory_data_size = (uint32)total_size_new;
|
||||
|
||||
memory->memory_data = memory_data_new;
|
||||
memory->memory_data_end = memory_data_new + (uint32)total_size_new;
|
||||
|
||||
#if WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0 || WASM_ENABLE_AOT != 0
|
||||
#if UINTPTR_MAX == UINT64_MAX
|
||||
memory->mem_bound_check_1byte.u64 = total_size_new - 1;
|
||||
memory->mem_bound_check_2bytes.u64 = total_size_new - 2;
|
||||
memory->mem_bound_check_4bytes.u64 = total_size_new - 4;
|
||||
memory->mem_bound_check_8bytes.u64 = total_size_new - 8;
|
||||
memory->mem_bound_check_16bytes.u64 = total_size_new - 16;
|
||||
#else
|
||||
memory->mem_bound_check_1byte.u32[0] = (uint32)total_size_new - 1;
|
||||
memory->mem_bound_check_2bytes.u32[0] = (uint32)total_size_new - 2;
|
||||
memory->mem_bound_check_4bytes.u32[0] = (uint32)total_size_new - 4;
|
||||
memory->mem_bound_check_8bytes.u32[0] = (uint32)total_size_new - 8;
|
||||
memory->mem_bound_check_16bytes.u32[0] = (uint32)total_size_new - 16;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
bool
|
||||
wasm_enlarge_memory(WASMModuleInstance *module, uint32 inc_page_count)
|
||||
{
|
||||
WASMMemoryInstance *memory = wasm_get_default_memory(module);
|
||||
uint32 num_bytes_per_page, total_size_old;
|
||||
uint32 cur_page_count, max_page_count, total_page_count;
|
||||
uint64 total_size_new;
|
||||
|
||||
if (!memory)
|
||||
return false;
|
||||
|
||||
num_bytes_per_page = memory->num_bytes_per_page;
|
||||
cur_page_count = memory->cur_page_count;
|
||||
max_page_count = memory->max_page_count;
|
||||
total_size_old = num_bytes_per_page * cur_page_count;
|
||||
total_page_count = inc_page_count + cur_page_count;
|
||||
total_size_new = num_bytes_per_page * (uint64)total_page_count;
|
||||
|
||||
if (inc_page_count <= 0)
|
||||
/* No need to enlarge memory */
|
||||
return true;
|
||||
|
||||
if (total_page_count < cur_page_count /* integer overflow */
|
||||
|| total_page_count > max_page_count) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bh_assert(total_size_new <= 4 * (uint64)BH_GB);
|
||||
if (total_size_new > UINT32_MAX) {
|
||||
/* Resize to 1 page with size 4G-1 */
|
||||
num_bytes_per_page = UINT32_MAX;
|
||||
total_page_count = max_page_count = 1;
|
||||
total_size_new = UINT32_MAX;
|
||||
}
|
||||
|
||||
#ifdef BH_PLATFORM_WINDOWS
|
||||
if (!os_mem_commit(memory->memory_data_end,
|
||||
(uint32)total_size_new - total_size_old,
|
||||
MMAP_PROT_READ | MMAP_PROT_WRITE)) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (os_mprotect(memory->memory_data_end,
|
||||
(uint32)total_size_new - total_size_old,
|
||||
MMAP_PROT_READ | MMAP_PROT_WRITE)
|
||||
!= 0) {
|
||||
#ifdef BH_PLATFORM_WINDOWS
|
||||
os_mem_decommit(memory->memory_data_end,
|
||||
(uint32)total_size_new - total_size_old);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
/* The increased pages are filled with zero by the OS when os_mmap,
|
||||
no need to memset it again here */
|
||||
|
||||
memory->num_bytes_per_page = num_bytes_per_page;
|
||||
memory->cur_page_count = total_page_count;
|
||||
memory->max_page_count = max_page_count;
|
||||
memory->memory_data_size = (uint32)total_size_new;
|
||||
memory->memory_data_end = memory->memory_data + (uint32)total_size_new;
|
||||
|
||||
#if WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0 || WASM_ENABLE_AOT != 0
|
||||
memory->mem_bound_check_1byte.u64 = total_size_new - 1;
|
||||
memory->mem_bound_check_2bytes.u64 = total_size_new - 2;
|
||||
memory->mem_bound_check_4bytes.u64 = total_size_new - 4;
|
||||
memory->mem_bound_check_8bytes.u64 = total_size_new - 8;
|
||||
memory->mem_bound_check_16bytes.u64 = total_size_new - 16;
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif /* end of OS_ENABLE_HW_BOUND_CHECK */
|
||||
|
|
|
@ -135,43 +135,117 @@ static os_thread_local_attribute WASMExecEnv *exec_env_tls = NULL;
|
|||
static void
|
||||
runtime_signal_handler(void *sig_addr)
|
||||
{
|
||||
WASMModuleInstanceCommon *module_inst;
|
||||
WASMSignalInfo sig_info;
|
||||
WASMModuleInstance *module_inst;
|
||||
WASMMemoryInstance *memory_inst;
|
||||
WASMJmpBuf *jmpbuf_node;
|
||||
uint8 *mapped_mem_start_addr = NULL;
|
||||
uint8 *mapped_mem_end_addr = NULL;
|
||||
uint8 *stack_min_addr;
|
||||
uint32 page_size;
|
||||
uint32 guard_page_count = STACK_OVERFLOW_CHECK_GUARD_PAGE_COUNT;
|
||||
|
||||
sig_info.exec_env_tls = exec_env_tls;
|
||||
sig_info.sig_addr = sig_addr;
|
||||
if (exec_env_tls) {
|
||||
module_inst = exec_env_tls->module_inst;
|
||||
#if WASM_ENABLE_INTERP != 0
|
||||
if (module_inst->module_type == Wasm_Module_Bytecode)
|
||||
wasm_signal_handler(&sig_info);
|
||||
#endif
|
||||
#if WASM_ENABLE_AOT != 0
|
||||
if (module_inst->module_type == Wasm_Module_AoT)
|
||||
aot_signal_handler(&sig_info);
|
||||
#endif
|
||||
/* Check whether current thread is running wasm function */
|
||||
if (exec_env_tls && exec_env_tls->handle == os_self_thread()
|
||||
&& (jmpbuf_node = exec_env_tls->jmpbuf_stack_top)) {
|
||||
/* Get mapped mem info of current instance */
|
||||
module_inst = (WASMModuleInstance *)exec_env_tls->module_inst;
|
||||
/* Get the default memory instance */
|
||||
memory_inst = wasm_get_default_memory(module_inst);
|
||||
if (memory_inst) {
|
||||
mapped_mem_start_addr = memory_inst->memory_data;
|
||||
mapped_mem_end_addr = memory_inst->memory_data + 8 * (uint64)BH_GB;
|
||||
}
|
||||
|
||||
/* Get stack info of current thread */
|
||||
page_size = os_getpagesize();
|
||||
stack_min_addr = os_thread_get_stack_boundary();
|
||||
|
||||
if (memory_inst
|
||||
&& (mapped_mem_start_addr <= (uint8 *)sig_addr
|
||||
&& (uint8 *)sig_addr < mapped_mem_end_addr)) {
|
||||
/* The address which causes segmentation fault is inside
|
||||
the memory instance's guard regions */
|
||||
wasm_set_exception(module_inst, "out of bounds memory access");
|
||||
os_longjmp(jmpbuf_node->jmpbuf, 1);
|
||||
}
|
||||
else if (stack_min_addr - page_size <= (uint8 *)sig_addr
|
||||
&& (uint8 *)sig_addr
|
||||
< stack_min_addr + page_size * guard_page_count) {
|
||||
/* The address which causes segmentation fault is inside
|
||||
native thread's guard page */
|
||||
wasm_set_exception(module_inst, "native stack overflow");
|
||||
os_longjmp(jmpbuf_node->jmpbuf, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
static LONG
|
||||
runtime_exception_handler(EXCEPTION_POINTERS *exce_info)
|
||||
{
|
||||
WASMModuleInstanceCommon *module_inst;
|
||||
WASMSignalInfo sig_info;
|
||||
PEXCEPTION_RECORD ExceptionRecord = exce_info->ExceptionRecord;
|
||||
uint8 *sig_addr = (uint8 *)ExceptionRecord->ExceptionInformation[1];
|
||||
WASMModuleInstance *module_inst;
|
||||
WASMMemoryInstance *memory_inst;
|
||||
WASMJmpBuf *jmpbuf_node;
|
||||
uint8 *mapped_mem_start_addr = NULL;
|
||||
uint8 *mapped_mem_end_addr = NULL;
|
||||
uint32 page_size = os_getpagesize();
|
||||
|
||||
sig_info.exec_env_tls = exec_env_tls;
|
||||
sig_info.exce_info = exce_info;
|
||||
if (exec_env_tls) {
|
||||
module_inst = exec_env_tls->module_inst;
|
||||
#if WASM_ENABLE_INTERP != 0
|
||||
if (module_inst->module_type == Wasm_Module_Bytecode)
|
||||
return wasm_exception_handler(&sig_info);
|
||||
#endif
|
||||
#if WASM_ENABLE_AOT != 0
|
||||
if (module_inst->module_type == Wasm_Module_AoT)
|
||||
return aot_exception_handler(&sig_info);
|
||||
#endif
|
||||
if (exec_env_tls && exec_env_tls->handle == os_self_thread()
|
||||
&& (jmpbuf_node = exec_env_tls->jmpbuf_stack_top)) {
|
||||
module_inst = (WASMModuleInstance *)exec_env_tls->module_inst;
|
||||
if (ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION) {
|
||||
/* Get the default memory instance */
|
||||
memory_inst = wasm_get_default_memory(module_inst);
|
||||
if (memory_inst) {
|
||||
mapped_mem_start_addr = memory_inst->memory_data;
|
||||
mapped_mem_end_addr =
|
||||
memory_inst->memory_data + 8 * (uint64)BH_GB;
|
||||
if (mapped_mem_start_addr <= (uint8 *)sig_addr
|
||||
&& (uint8 *)sig_addr < mapped_mem_end_addr) {
|
||||
/* The address which causes segmentation fault is inside
|
||||
the memory instance's guard regions.
|
||||
Set exception and let the wasm func continue to run, when
|
||||
the wasm func returns, the caller will check whether the
|
||||
exception is thrown and return to runtime. */
|
||||
wasm_set_exception(module_inst,
|
||||
"out of bounds memory access");
|
||||
if (module_inst->module_type == Wasm_Module_Bytecode) {
|
||||
/* Continue to search next exception handler for
|
||||
interpreter mode as it can be caught by
|
||||
`__try { .. } __except { .. }` sentences in
|
||||
wasm_runtime.c */
|
||||
return EXCEPTION_CONTINUE_SEARCH;
|
||||
}
|
||||
else {
|
||||
/* Skip current instruction and continue to run for
|
||||
AOT mode. TODO: implement unwind support for AOT
|
||||
code in Windows platform */
|
||||
exce_info->ContextRecord->Rip++;
|
||||
return EXCEPTION_CONTINUE_EXECUTION;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (ExceptionRecord->ExceptionCode == EXCEPTION_STACK_OVERFLOW) {
|
||||
/* Set stack overflow exception and let the wasm func continue
|
||||
to run, when the wasm func returns, the caller will check
|
||||
whether the exception is thrown and return to runtime, and
|
||||
the damaged stack will be recovered by _resetstkoflw(). */
|
||||
wasm_set_exception(module_inst, "native stack overflow");
|
||||
if (module_inst->module_type == Wasm_Module_Bytecode) {
|
||||
return EXCEPTION_CONTINUE_SEARCH;
|
||||
}
|
||||
else {
|
||||
return EXCEPTION_CONTINUE_EXECUTION;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
os_printf("Unhandled exception thrown: exception code: 0x%lx, "
|
||||
"exception address: %p, exception information: %p\n",
|
||||
ExceptionRecord->ExceptionCode, ExceptionRecord->ExceptionAddress,
|
||||
sig_addr);
|
||||
return EXCEPTION_CONTINUE_SEARCH;
|
||||
}
|
||||
#endif /* end of BH_PLATFORM_WINDOWS */
|
||||
|
@ -912,22 +986,7 @@ wasm_runtime_load(uint8 *buf, uint32 size, char *error_buf,
|
|||
WASMModuleCommon *module_common = NULL;
|
||||
|
||||
if (get_package_type(buf, size) == Wasm_Module_Bytecode) {
|
||||
#if WASM_ENABLE_AOT != 0 && WASM_ENABLE_JIT != 0
|
||||
AOTModule *aot_module;
|
||||
WASMModule *module = wasm_load(buf, size, error_buf, error_buf_size);
|
||||
if (!module)
|
||||
return NULL;
|
||||
|
||||
if (!(aot_module =
|
||||
aot_convert_wasm_module(module, error_buf, error_buf_size))) {
|
||||
wasm_unload(module);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
module_common = (WASMModuleCommon *)aot_module;
|
||||
return register_module_with_null_name(module_common, error_buf,
|
||||
error_buf_size);
|
||||
#elif WASM_ENABLE_INTERP != 0
|
||||
#if WASM_ENABLE_INTERP != 0
|
||||
module_common =
|
||||
(WASMModuleCommon *)wasm_load(buf, size, error_buf, error_buf_size);
|
||||
return register_module_with_null_name(module_common, error_buf,
|
||||
|
@ -1235,19 +1294,18 @@ wasm_runtime_dump_mem_consumption(WASMExecEnv *exec_env)
|
|||
&module_inst_mem_consps);
|
||||
wasm_get_module_mem_consumption(wasm_module, &module_mem_consps);
|
||||
if (wasm_module_inst->module->aux_stack_top_global_index != (uint32)-1)
|
||||
max_aux_stack_used = wasm_module_inst->max_aux_stack_used;
|
||||
max_aux_stack_used = wasm_module_inst->e->max_aux_stack_used;
|
||||
}
|
||||
#endif
|
||||
#if WASM_ENABLE_AOT != 0
|
||||
if (module_inst_common->module_type == Wasm_Module_AoT) {
|
||||
AOTModuleInstance *aot_module_inst =
|
||||
(AOTModuleInstance *)module_inst_common;
|
||||
AOTModule *aot_module = (AOTModule *)aot_module_inst->aot_module.ptr;
|
||||
AOTModule *aot_module = (AOTModule *)aot_module_inst->module;
|
||||
module_common = (WASMModuleCommon *)aot_module;
|
||||
if (aot_module_inst->memories.ptr) {
|
||||
AOTMemoryInstance **memories =
|
||||
(AOTMemoryInstance **)aot_module_inst->memories.ptr;
|
||||
heap_handle = memories[0]->heap_handle.ptr;
|
||||
if (aot_module_inst->memories) {
|
||||
AOTMemoryInstance **memories = aot_module_inst->memories;
|
||||
heap_handle = memories[0]->heap_handle;
|
||||
}
|
||||
aot_get_module_inst_mem_consumption(aot_module_inst,
|
||||
&module_inst_mem_consps);
|
||||
|
@ -1982,99 +2040,130 @@ fail1:
|
|||
}
|
||||
|
||||
bool
|
||||
wasm_runtime_create_exec_env_singleton(WASMModuleInstanceCommon *module_inst)
|
||||
wasm_runtime_create_exec_env_singleton(
|
||||
WASMModuleInstanceCommon *module_inst_comm)
|
||||
{
|
||||
#if WASM_ENABLE_INTERP != 0
|
||||
if (module_inst->module_type == Wasm_Module_Bytecode)
|
||||
return wasm_create_exec_env_singleton(
|
||||
(WASMModuleInstance *)module_inst);
|
||||
#endif
|
||||
#if WASM_ENABLE_AOT != 0
|
||||
if (module_inst->module_type == Wasm_Module_AoT)
|
||||
return aot_create_exec_env_singleton((AOTModuleInstance *)module_inst);
|
||||
#endif
|
||||
return false;
|
||||
WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm;
|
||||
WASMExecEnv *exec_env = NULL;
|
||||
|
||||
bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
|
||||
|| module_inst_comm->module_type == Wasm_Module_AoT);
|
||||
|
||||
if (module_inst->exec_env_singleton) {
|
||||
return true;
|
||||
}
|
||||
|
||||
exec_env = wasm_exec_env_create(module_inst_comm,
|
||||
module_inst->default_wasm_stack_size);
|
||||
if (exec_env)
|
||||
module_inst->exec_env_singleton = exec_env;
|
||||
|
||||
return exec_env ? true : false;
|
||||
}
|
||||
|
||||
WASMExecEnv *
|
||||
wasm_runtime_get_exec_env_singleton(WASMModuleInstanceCommon *module_inst)
|
||||
wasm_runtime_get_exec_env_singleton(WASMModuleInstanceCommon *module_inst_comm)
|
||||
{
|
||||
#if WASM_ENABLE_INTERP != 0
|
||||
if (module_inst->module_type == Wasm_Module_Bytecode) {
|
||||
if (!((WASMModuleInstance *)module_inst)->exec_env_singleton) {
|
||||
wasm_create_exec_env_singleton((WASMModuleInstance *)module_inst);
|
||||
}
|
||||
return ((WASMModuleInstance *)module_inst)->exec_env_singleton;
|
||||
WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm;
|
||||
|
||||
bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
|
||||
|| module_inst_comm->module_type == Wasm_Module_AoT);
|
||||
|
||||
if (!module_inst->exec_env_singleton) {
|
||||
wasm_runtime_create_exec_env_singleton(module_inst_comm);
|
||||
}
|
||||
#endif
|
||||
#if WASM_ENABLE_AOT != 0
|
||||
if (module_inst->module_type == Wasm_Module_AoT) {
|
||||
if (!((AOTModuleInstance *)module_inst)->exec_env_singleton.ptr) {
|
||||
aot_create_exec_env_singleton((AOTModuleInstance *)module_inst);
|
||||
}
|
||||
return (WASMExecEnv *)((AOTModuleInstance *)module_inst)
|
||||
->exec_env_singleton.ptr;
|
||||
}
|
||||
#endif
|
||||
return NULL;
|
||||
return module_inst->exec_env_singleton;
|
||||
}
|
||||
|
||||
void
|
||||
wasm_runtime_set_exception(WASMModuleInstanceCommon *module_inst,
|
||||
const char *exception)
|
||||
wasm_set_exception(WASMModuleInstance *module_inst, const char *exception)
|
||||
{
|
||||
#if WASM_ENABLE_INTERP != 0
|
||||
if (module_inst->module_type == Wasm_Module_Bytecode) {
|
||||
wasm_set_exception((WASMModuleInstance *)module_inst, exception);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#if WASM_ENABLE_AOT != 0
|
||||
if (module_inst->module_type == Wasm_Module_AoT) {
|
||||
aot_set_exception((AOTModuleInstance *)module_inst, exception);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if (exception)
|
||||
snprintf(module_inst->cur_exception, sizeof(module_inst->cur_exception),
|
||||
"Exception: %s", exception);
|
||||
else
|
||||
module_inst->cur_exception[0] = '\0';
|
||||
}
|
||||
|
||||
/* clang-format off */
|
||||
static const char *exception_msgs[] = {
|
||||
"unreachable", /* EXCE_UNREACHABLE */
|
||||
"allocate memory failed", /* EXCE_OUT_OF_MEMORY */
|
||||
"out of bounds memory access", /* EXCE_OUT_OF_BOUNDS_MEMORY_ACCESS */
|
||||
"integer overflow", /* EXCE_INTEGER_OVERFLOW */
|
||||
"integer divide by zero", /* EXCE_INTEGER_DIVIDE_BY_ZERO */
|
||||
"invalid conversion to integer", /* EXCE_INVALID_CONVERSION_TO_INTEGER */
|
||||
"indirect call type mismatch", /* EXCE_INVALID_FUNCTION_TYPE_INDEX */
|
||||
"invalid function index", /* EXCE_INVALID_FUNCTION_INDEX */
|
||||
"undefined element", /* EXCE_UNDEFINED_ELEMENT */
|
||||
"uninitialized element", /* EXCE_UNINITIALIZED_ELEMENT */
|
||||
"failed to call unlinked import function", /* EXCE_CALL_UNLINKED_IMPORT_FUNC */
|
||||
"native stack overflow", /* EXCE_NATIVE_STACK_OVERFLOW */
|
||||
"unaligned atomic", /* EXCE_UNALIGNED_ATOMIC */
|
||||
"wasm auxiliary stack overflow", /* EXCE_AUX_STACK_OVERFLOW */
|
||||
"wasm auxiliary stack underflow", /* EXCE_AUX_STACK_UNDERFLOW */
|
||||
"out of bounds table access", /* EXCE_OUT_OF_BOUNDS_TABLE_ACCESS */
|
||||
"wasm operand stack overflow", /* EXCE_OPERAND_STACK_OVERFLOW */
|
||||
"", /* EXCE_ALREADY_THROWN */
|
||||
};
|
||||
/* clang-format on */
|
||||
|
||||
void
|
||||
wasm_set_exception_with_id(WASMModuleInstance *module_inst, uint32 id)
|
||||
{
|
||||
if (id < EXCE_NUM)
|
||||
wasm_set_exception(module_inst, exception_msgs[id]);
|
||||
else
|
||||
wasm_set_exception(module_inst, "unknown exception");
|
||||
}
|
||||
|
||||
const char *
|
||||
wasm_runtime_get_exception(WASMModuleInstanceCommon *module_inst)
|
||||
wasm_get_exception(WASMModuleInstance *module_inst)
|
||||
{
|
||||
#if WASM_ENABLE_INTERP != 0
|
||||
if (module_inst->module_type == Wasm_Module_Bytecode) {
|
||||
return wasm_get_exception((WASMModuleInstance *)module_inst);
|
||||
}
|
||||
#endif
|
||||
#if WASM_ENABLE_AOT != 0
|
||||
if (module_inst->module_type == Wasm_Module_AoT) {
|
||||
return aot_get_exception((AOTModuleInstance *)module_inst);
|
||||
}
|
||||
#endif
|
||||
return NULL;
|
||||
if (module_inst->cur_exception[0] == '\0')
|
||||
return NULL;
|
||||
else
|
||||
return module_inst->cur_exception;
|
||||
}
|
||||
|
||||
void
|
||||
wasm_runtime_clear_exception(WASMModuleInstanceCommon *module_inst)
|
||||
wasm_runtime_set_exception(WASMModuleInstanceCommon *module_inst_comm,
|
||||
const char *exception)
|
||||
{
|
||||
wasm_runtime_set_exception(module_inst, NULL);
|
||||
WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm;
|
||||
|
||||
bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
|
||||
|| module_inst_comm->module_type == Wasm_Module_AoT);
|
||||
wasm_set_exception(module_inst, exception);
|
||||
}
|
||||
|
||||
const char *
|
||||
wasm_runtime_get_exception(WASMModuleInstanceCommon *module_inst_comm)
|
||||
{
|
||||
WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm;
|
||||
|
||||
bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
|
||||
|| module_inst_comm->module_type == Wasm_Module_AoT);
|
||||
return wasm_get_exception(module_inst);
|
||||
}
|
||||
|
||||
void
|
||||
wasm_runtime_set_custom_data_internal(WASMModuleInstanceCommon *module_inst,
|
||||
void *custom_data)
|
||||
wasm_runtime_clear_exception(WASMModuleInstanceCommon *module_inst_comm)
|
||||
{
|
||||
#if WASM_ENABLE_INTERP != 0
|
||||
if (module_inst->module_type == Wasm_Module_Bytecode) {
|
||||
((WASMModuleInstance *)module_inst)->custom_data = custom_data;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#if WASM_ENABLE_AOT != 0
|
||||
if (module_inst->module_type == Wasm_Module_AoT) {
|
||||
((AOTModuleInstance *)module_inst)->custom_data.ptr = custom_data;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
|
||||
|| module_inst_comm->module_type == Wasm_Module_AoT);
|
||||
wasm_runtime_set_exception(module_inst_comm, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
wasm_runtime_set_custom_data_internal(
|
||||
WASMModuleInstanceCommon *module_inst_comm, void *custom_data)
|
||||
{
|
||||
WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm;
|
||||
|
||||
bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
|
||||
|| module_inst_comm->module_type == Wasm_Module_AoT);
|
||||
module_inst->custom_data = custom_data;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -2089,17 +2178,13 @@ wasm_runtime_set_custom_data(WASMModuleInstanceCommon *module_inst,
|
|||
}
|
||||
|
||||
void *
|
||||
wasm_runtime_get_custom_data(WASMModuleInstanceCommon *module_inst)
|
||||
wasm_runtime_get_custom_data(WASMModuleInstanceCommon *module_inst_comm)
|
||||
{
|
||||
#if WASM_ENABLE_INTERP != 0
|
||||
if (module_inst->module_type == Wasm_Module_Bytecode)
|
||||
return ((WASMModuleInstance *)module_inst)->custom_data;
|
||||
#endif
|
||||
#if WASM_ENABLE_AOT != 0
|
||||
if (module_inst->module_type == Wasm_Module_AoT)
|
||||
return ((AOTModuleInstance *)module_inst)->custom_data.ptr;
|
||||
#endif
|
||||
return NULL;
|
||||
WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm;
|
||||
|
||||
bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
|
||||
|| module_inst_comm->module_type == Wasm_Module_AoT);
|
||||
return module_inst->custom_data;
|
||||
}
|
||||
|
||||
uint32
|
||||
|
@ -2171,155 +2256,6 @@ wasm_runtime_module_dup_data(WASMModuleInstanceCommon *module_inst,
|
|||
return 0;
|
||||
}
|
||||
|
||||
bool
|
||||
wasm_runtime_validate_app_addr(WASMModuleInstanceCommon *module_inst,
|
||||
uint32 app_offset, uint32 size)
|
||||
{
|
||||
#if WASM_ENABLE_INTERP != 0
|
||||
if (module_inst->module_type == Wasm_Module_Bytecode)
|
||||
return wasm_validate_app_addr((WASMModuleInstance *)module_inst,
|
||||
app_offset, size);
|
||||
#endif
|
||||
#if WASM_ENABLE_AOT != 0
|
||||
if (module_inst->module_type == Wasm_Module_AoT)
|
||||
return aot_validate_app_addr((AOTModuleInstance *)module_inst,
|
||||
app_offset, size);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
wasm_runtime_validate_app_str_addr(WASMModuleInstanceCommon *module_inst,
|
||||
uint32 app_str_offset)
|
||||
{
|
||||
uint32 app_end_offset;
|
||||
char *str, *str_end;
|
||||
|
||||
if (!wasm_runtime_get_app_addr_range(module_inst, app_str_offset, NULL,
|
||||
&app_end_offset))
|
||||
goto fail;
|
||||
|
||||
str = wasm_runtime_addr_app_to_native(module_inst, app_str_offset);
|
||||
str_end = str + (app_end_offset - app_str_offset);
|
||||
while (str < str_end && *str != '\0')
|
||||
str++;
|
||||
if (str == str_end)
|
||||
goto fail;
|
||||
return true;
|
||||
|
||||
fail:
|
||||
wasm_runtime_set_exception(module_inst, "out of bounds memory access");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
wasm_runtime_validate_native_addr(WASMModuleInstanceCommon *module_inst,
|
||||
void *native_ptr, uint32 size)
|
||||
{
|
||||
#if WASM_ENABLE_INTERP != 0
|
||||
if (module_inst->module_type == Wasm_Module_Bytecode)
|
||||
return wasm_validate_native_addr((WASMModuleInstance *)module_inst,
|
||||
native_ptr, size);
|
||||
#endif
|
||||
#if WASM_ENABLE_AOT != 0
|
||||
if (module_inst->module_type == Wasm_Module_AoT)
|
||||
return aot_validate_native_addr((AOTModuleInstance *)module_inst,
|
||||
native_ptr, size);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
void *
|
||||
wasm_runtime_addr_app_to_native(WASMModuleInstanceCommon *module_inst,
|
||||
uint32 app_offset)
|
||||
{
|
||||
#if WASM_ENABLE_INTERP != 0
|
||||
if (module_inst->module_type == Wasm_Module_Bytecode)
|
||||
return wasm_addr_app_to_native((WASMModuleInstance *)module_inst,
|
||||
app_offset);
|
||||
#endif
|
||||
#if WASM_ENABLE_AOT != 0
|
||||
if (module_inst->module_type == Wasm_Module_AoT)
|
||||
return aot_addr_app_to_native((AOTModuleInstance *)module_inst,
|
||||
app_offset);
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint32
|
||||
wasm_runtime_addr_native_to_app(WASMModuleInstanceCommon *module_inst,
|
||||
void *native_ptr)
|
||||
{
|
||||
#if WASM_ENABLE_INTERP != 0
|
||||
if (module_inst->module_type == Wasm_Module_Bytecode)
|
||||
return wasm_addr_native_to_app((WASMModuleInstance *)module_inst,
|
||||
native_ptr);
|
||||
#endif
|
||||
#if WASM_ENABLE_AOT != 0
|
||||
if (module_inst->module_type == Wasm_Module_AoT)
|
||||
return aot_addr_native_to_app((AOTModuleInstance *)module_inst,
|
||||
native_ptr);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool
|
||||
wasm_runtime_get_app_addr_range(WASMModuleInstanceCommon *module_inst,
|
||||
uint32 app_offset, uint32 *p_app_start_offset,
|
||||
uint32 *p_app_end_offset)
|
||||
{
|
||||
#if WASM_ENABLE_INTERP != 0
|
||||
if (module_inst->module_type == Wasm_Module_Bytecode)
|
||||
return wasm_get_app_addr_range((WASMModuleInstance *)module_inst,
|
||||
app_offset, p_app_start_offset,
|
||||
p_app_end_offset);
|
||||
#endif
|
||||
#if WASM_ENABLE_AOT != 0
|
||||
if (module_inst->module_type == Wasm_Module_AoT)
|
||||
return aot_get_app_addr_range((AOTModuleInstance *)module_inst,
|
||||
app_offset, p_app_start_offset,
|
||||
p_app_end_offset);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
wasm_runtime_get_native_addr_range(WASMModuleInstanceCommon *module_inst,
|
||||
uint8 *native_ptr,
|
||||
uint8 **p_native_start_addr,
|
||||
uint8 **p_native_end_addr)
|
||||
{
|
||||
#if WASM_ENABLE_INTERP != 0
|
||||
if (module_inst->module_type == Wasm_Module_Bytecode)
|
||||
return wasm_get_native_addr_range((WASMModuleInstance *)module_inst,
|
||||
native_ptr, p_native_start_addr,
|
||||
p_native_end_addr);
|
||||
#endif
|
||||
#if WASM_ENABLE_AOT != 0
|
||||
if (module_inst->module_type == Wasm_Module_AoT)
|
||||
return aot_get_native_addr_range((AOTModuleInstance *)module_inst,
|
||||
native_ptr, p_native_start_addr,
|
||||
p_native_end_addr);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
wasm_runtime_enlarge_memory(WASMModuleInstanceCommon *module,
|
||||
uint32 inc_page_count)
|
||||
{
|
||||
#if WASM_ENABLE_INTERP != 0
|
||||
if (module->module_type == Wasm_Module_Bytecode)
|
||||
return wasm_enlarge_memory((WASMModuleInstance *)module,
|
||||
inc_page_count);
|
||||
#endif
|
||||
#if WASM_ENABLE_AOT != 0
|
||||
if (module->module_type == Wasm_Module_AoT)
|
||||
return aot_enlarge_memory((AOTModuleInstance *)module, inc_page_count);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_LIBC_WASI != 0
|
||||
|
||||
static WASIArguments *
|
||||
|
@ -2477,19 +2413,6 @@ wasm_runtime_init_wasi(WASMModuleInstanceCommon *module_inst,
|
|||
|
||||
wasm_runtime_set_wasi_ctx(module_inst, wasi_ctx);
|
||||
|
||||
#if WASM_ENABLE_INTERP != 0
|
||||
if (module_inst->module_type == Wasm_Module_Bytecode
|
||||
&& !((WASMModuleInstance *)module_inst)->default_memory)
|
||||
return true;
|
||||
#endif
|
||||
#if WASM_ENABLE_AOT != 0
|
||||
if (module_inst->module_type == Wasm_Module_AoT
|
||||
&& !((AOTModuleInstance *)module_inst)
|
||||
->global_table_data.memory_instances[0]
|
||||
.memory_data.ptr)
|
||||
return true;
|
||||
#endif
|
||||
|
||||
/* process argv[0], trip the path and suffix, only keep the program name */
|
||||
if (!copy_string_array((const char **)argv, argc, &argv_buf, &argv_list,
|
||||
&argv_buf_size)) {
|
||||
|
@ -2796,7 +2719,7 @@ wasm_runtime_is_wasi_mode(WASMModuleInstanceCommon *module_inst)
|
|||
#endif
|
||||
#if WASM_ENABLE_AOT != 0
|
||||
if (module_inst->module_type == Wasm_Module_AoT
|
||||
&& ((AOTModule *)((AOTModuleInstance *)module_inst)->aot_module.ptr)
|
||||
&& ((AOTModule *)((AOTModuleInstance *)module_inst)->module)
|
||||
->import_wasi_api)
|
||||
return true;
|
||||
#endif
|
||||
|
@ -2832,7 +2755,7 @@ wasm_runtime_lookup_wasi_start_function(WASMModuleInstanceCommon *module_inst)
|
|||
if (module_inst->module_type == Wasm_Module_AoT) {
|
||||
AOTModuleInstance *aot_inst = (AOTModuleInstance *)module_inst;
|
||||
AOTFunctionInstance *export_funcs =
|
||||
(AOTFunctionInstance *)aot_inst->export_funcs.ptr;
|
||||
(AOTFunctionInstance *)aot_inst->export_functions;
|
||||
for (i = 0; i < aot_inst->export_func_count; i++) {
|
||||
if (!strcmp(export_funcs[i].func_name, "_start")) {
|
||||
AOTFuncType *func_type = export_funcs[i].u.func.func_type;
|
||||
|
@ -2905,49 +2828,37 @@ wasm_runtime_destroy_wasi(WASMModuleInstanceCommon *module_inst)
|
|||
#endif
|
||||
|
||||
WASIContext *
|
||||
wasm_runtime_get_wasi_ctx(WASMModuleInstanceCommon *module_inst)
|
||||
wasm_runtime_get_wasi_ctx(WASMModuleInstanceCommon *module_inst_comm)
|
||||
{
|
||||
#if WASM_ENABLE_INTERP != 0
|
||||
if (module_inst->module_type == Wasm_Module_Bytecode)
|
||||
return ((WASMModuleInstance *)module_inst)->wasi_ctx;
|
||||
#endif
|
||||
#if WASM_ENABLE_AOT != 0
|
||||
if (module_inst->module_type == Wasm_Module_AoT)
|
||||
return ((AOTModuleInstance *)module_inst)->wasi_ctx.ptr;
|
||||
#endif
|
||||
return NULL;
|
||||
WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm;
|
||||
|
||||
bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
|
||||
|| module_inst_comm->module_type == Wasm_Module_AoT);
|
||||
return module_inst->wasi_ctx;
|
||||
}
|
||||
|
||||
void
|
||||
wasm_runtime_set_wasi_ctx(WASMModuleInstanceCommon *module_inst,
|
||||
wasm_runtime_set_wasi_ctx(WASMModuleInstanceCommon *module_inst_comm,
|
||||
WASIContext *wasi_ctx)
|
||||
{
|
||||
#if WASM_ENABLE_INTERP != 0
|
||||
if (module_inst->module_type == Wasm_Module_Bytecode)
|
||||
((WASMModuleInstance *)module_inst)->wasi_ctx = wasi_ctx;
|
||||
#endif
|
||||
#if WASM_ENABLE_AOT != 0
|
||||
if (module_inst->module_type == Wasm_Module_AoT)
|
||||
((AOTModuleInstance *)module_inst)->wasi_ctx.ptr = wasi_ctx;
|
||||
#endif
|
||||
WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm;
|
||||
|
||||
bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
|
||||
|| module_inst_comm->module_type == Wasm_Module_AoT);
|
||||
module_inst->wasi_ctx = wasi_ctx;
|
||||
}
|
||||
#endif /* end of WASM_ENABLE_LIBC_WASI */
|
||||
|
||||
WASMModuleCommon *
|
||||
wasm_exec_env_get_module(WASMExecEnv *exec_env)
|
||||
{
|
||||
WASMModuleInstanceCommon *module_inst =
|
||||
WASMModuleInstanceCommon *module_inst_comm =
|
||||
wasm_runtime_get_module_inst(exec_env);
|
||||
#if WASM_ENABLE_INTERP != 0
|
||||
if (module_inst->module_type == Wasm_Module_Bytecode)
|
||||
return (WASMModuleCommon *)((WASMModuleInstance *)module_inst)->module;
|
||||
#endif
|
||||
#if WASM_ENABLE_AOT != 0
|
||||
if (module_inst->module_type == Wasm_Module_AoT)
|
||||
return (WASMModuleCommon *)((AOTModuleInstance *)module_inst)
|
||||
->aot_module.ptr;
|
||||
#endif
|
||||
return NULL;
|
||||
WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm;
|
||||
|
||||
bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
|
||||
|| module_inst_comm->module_type == Wasm_Module_AoT);
|
||||
return (WASMModuleCommon *)module_inst->module;
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_LOAD_CUSTOM_SECTION != 0
|
||||
|
@ -4510,8 +4421,8 @@ interp_mark_all_externrefs(WASMModuleInstance *module_inst)
|
|||
WASMGlobalInstance *global;
|
||||
WASMTableInstance *table;
|
||||
|
||||
global = module_inst->globals;
|
||||
for (i = 0; i < module_inst->global_count; i++, global++) {
|
||||
global = module_inst->e->globals;
|
||||
for (i = 0; i < module_inst->e->global_count; i++, global++) {
|
||||
if (global->type == VALUE_TYPE_EXTERNREF) {
|
||||
externref_idx = *(uint32 *)(global_data + global->data_offset);
|
||||
mark_externref(externref_idx);
|
||||
|
@ -4519,14 +4430,23 @@ interp_mark_all_externrefs(WASMModuleInstance *module_inst)
|
|||
}
|
||||
|
||||
for (i = 0; i < module_inst->table_count; i++) {
|
||||
uint8 elem_type = 0;
|
||||
uint32 init_size, max_size;
|
||||
|
||||
table = wasm_get_table_inst(module_inst, i);
|
||||
if (table->elem_type == VALUE_TYPE_EXTERNREF) {
|
||||
table_data = (uint32 *)table->base_addr;
|
||||
(void)wasm_runtime_get_table_inst_elem_type(
|
||||
(WASMModuleInstanceCommon *)module_inst, i, &elem_type, &init_size,
|
||||
&max_size);
|
||||
|
||||
if (elem_type == VALUE_TYPE_EXTERNREF) {
|
||||
table_data = table->elems;
|
||||
for (j = 0; j < table->cur_size; j++) {
|
||||
externref_idx = table_data[j];
|
||||
mark_externref(externref_idx);
|
||||
}
|
||||
}
|
||||
(void)init_size;
|
||||
(void)max_size;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -4536,25 +4456,23 @@ static void
|
|||
aot_mark_all_externrefs(AOTModuleInstance *module_inst)
|
||||
{
|
||||
uint32 i = 0, j = 0;
|
||||
const AOTModule *module = (AOTModule *)(module_inst->aot_module.ptr);
|
||||
const AOTModule *module = (AOTModule *)module_inst->module;
|
||||
const AOTTable *table = module->tables;
|
||||
const AOTGlobal *global = module->globals;
|
||||
const AOTTableInstance *table_inst =
|
||||
(AOTTableInstance *)module_inst->tables.ptr;
|
||||
const AOTTableInstance *table_inst;
|
||||
|
||||
for (i = 0; i < module->global_count; i++, global++) {
|
||||
if (global->type == VALUE_TYPE_EXTERNREF) {
|
||||
mark_externref(*(uint32 *)((uint8 *)module_inst->global_data.ptr
|
||||
+ global->data_offset));
|
||||
mark_externref(
|
||||
*(uint32 *)(module_inst->global_data + global->data_offset));
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < module->table_count;
|
||||
i++, table_inst = aot_next_tbl_inst(table_inst)) {
|
||||
|
||||
for (i = 0; i < module->table_count; i++) {
|
||||
table_inst = module_inst->tables[i];
|
||||
if ((table + i)->elem_type == VALUE_TYPE_EXTERNREF) {
|
||||
while (j < table_inst->cur_size) {
|
||||
mark_externref(table_inst->data[j++]);
|
||||
mark_externref(table_inst->elems[j++]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4707,6 +4625,82 @@ wasm_runtime_dump_call_stack_to_buf(wasm_exec_env_t exec_env, char *buf,
|
|||
}
|
||||
#endif /* end of WASM_ENABLE_DUMP_CALL_STACK */
|
||||
|
||||
bool
|
||||
wasm_runtime_get_table_elem_type(const WASMModuleCommon *module_comm,
|
||||
uint32 table_idx, uint8 *out_elem_type,
|
||||
uint32 *out_min_size, uint32 *out_max_size)
|
||||
{
|
||||
#if WASM_ENABLE_INTERP != 0
|
||||
if (module_comm->module_type == Wasm_Module_Bytecode) {
|
||||
WASMModule *module = (WASMModule *)module_comm;
|
||||
|
||||
if (table_idx < module->import_table_count) {
|
||||
WASMTableImport *import_table =
|
||||
&((module->import_tables + table_idx)->u.table);
|
||||
*out_elem_type = import_table->elem_type;
|
||||
*out_min_size = import_table->init_size;
|
||||
*out_max_size = import_table->max_size;
|
||||
}
|
||||
else {
|
||||
WASMTable *table =
|
||||
module->tables + (table_idx - module->import_table_count);
|
||||
*out_elem_type = table->elem_type;
|
||||
*out_min_size = table->init_size;
|
||||
*out_max_size = table->max_size;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_AOT != 0
|
||||
if (module_comm->module_type == Wasm_Module_AoT) {
|
||||
AOTModule *module = (AOTModule *)module_comm;
|
||||
|
||||
if (table_idx < module->import_table_count) {
|
||||
AOTImportTable *import_table = module->import_tables + table_idx;
|
||||
*out_elem_type = VALUE_TYPE_FUNCREF;
|
||||
*out_min_size = import_table->table_init_size;
|
||||
*out_max_size = import_table->table_max_size;
|
||||
}
|
||||
else {
|
||||
AOTTable *table =
|
||||
module->tables + (table_idx - module->import_table_count);
|
||||
*out_elem_type = table->elem_type;
|
||||
*out_min_size = table->table_init_size;
|
||||
*out_max_size = table->table_max_size;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
wasm_runtime_get_table_inst_elem_type(
|
||||
const WASMModuleInstanceCommon *module_inst_comm, uint32 table_idx,
|
||||
uint8 *out_elem_type, uint32 *out_min_size, uint32 *out_max_size)
|
||||
{
|
||||
#if WASM_ENABLE_INTERP != 0
|
||||
if (module_inst_comm->module_type == Wasm_Module_Bytecode) {
|
||||
WASMModuleInstance *module_inst =
|
||||
(WASMModuleInstance *)module_inst_comm;
|
||||
return wasm_runtime_get_table_elem_type(
|
||||
(WASMModuleCommon *)module_inst->module, table_idx, out_elem_type,
|
||||
out_min_size, out_max_size);
|
||||
}
|
||||
#endif
|
||||
#if WASM_ENABLE_AOT != 0
|
||||
if (module_inst_comm->module_type == Wasm_Module_AoT) {
|
||||
AOTModuleInstance *module_inst = (AOTModuleInstance *)module_inst_comm;
|
||||
return wasm_runtime_get_table_elem_type(
|
||||
(WASMModuleCommon *)module_inst->module, table_idx, out_elem_type,
|
||||
out_min_size, out_max_size);
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
wasm_runtime_get_export_func_type(const WASMModuleCommon *module_comm,
|
||||
const WASMExport *export, WASMType **out)
|
||||
|
@ -4847,50 +4841,8 @@ wasm_runtime_get_export_table_type(const WASMModuleCommon *module_comm,
|
|||
uint8 *out_elem_type, uint32 *out_min_size,
|
||||
uint32 *out_max_size)
|
||||
{
|
||||
#if WASM_ENABLE_INTERP != 0
|
||||
if (module_comm->module_type == Wasm_Module_Bytecode) {
|
||||
WASMModule *module = (WASMModule *)module_comm;
|
||||
|
||||
if (export->index < module->import_table_count) {
|
||||
WASMTableImport *import_table =
|
||||
&((module->import_tables + export->index)->u.table);
|
||||
*out_elem_type = import_table->elem_type;
|
||||
*out_min_size = import_table->init_size;
|
||||
*out_max_size = import_table->max_size;
|
||||
}
|
||||
else {
|
||||
WASMTable *table =
|
||||
module->tables + (export->index - module->import_table_count);
|
||||
*out_elem_type = table->elem_type;
|
||||
*out_min_size = table->init_size;
|
||||
*out_max_size = table->max_size;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_AOT != 0
|
||||
if (module_comm->module_type == Wasm_Module_AoT) {
|
||||
AOTModule *module = (AOTModule *)module_comm;
|
||||
|
||||
if (export->index < module->import_table_count) {
|
||||
AOTImportTable *import_table =
|
||||
module->import_tables + export->index;
|
||||
*out_elem_type = VALUE_TYPE_FUNCREF;
|
||||
*out_min_size = import_table->table_init_size;
|
||||
*out_max_size = import_table->table_max_size;
|
||||
}
|
||||
else {
|
||||
AOTTable *table =
|
||||
module->tables + (export->index - module->import_table_count);
|
||||
*out_elem_type = table->elem_type;
|
||||
*out_min_size = table->table_init_size;
|
||||
*out_max_size = table->table_max_size;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
return wasm_runtime_get_table_elem_type(
|
||||
module_comm, export->index, out_elem_type, out_min_size, out_max_size);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
|
@ -5036,10 +4988,13 @@ wasm_runtime_invoke_c_api_native(WASMModuleInstanceCommon *module_inst,
|
|||
if (trap) {
|
||||
if (trap->message->data) {
|
||||
/* since trap->message->data does not end with '\0' */
|
||||
char trap_message[128] = { 0 };
|
||||
bh_memcpy_s(trap_message, 127, trap->message->data,
|
||||
(trap->message->size < 127 ? (uint32)trap->message->size
|
||||
: 127));
|
||||
char trap_message[108] = { 0 };
|
||||
uint32 max_size_to_copy = (uint32)sizeof(trap_message) - 1;
|
||||
uint32 size_to_copy = (trap->message->size < max_size_to_copy)
|
||||
? (uint32)trap->message->size
|
||||
: max_size_to_copy;
|
||||
bh_memcpy_s(trap_message, (uint32)sizeof(trap_message),
|
||||
trap->message->data, size_to_copy);
|
||||
wasm_runtime_set_exception(module_inst, trap_message);
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -852,17 +852,6 @@ wasm_runtime_dump_line_buf_impl(const char *line_buf, bool dump_or_print,
|
|||
WASMModuleCommon *
|
||||
wasm_exec_env_get_module(WASMExecEnv *exec_env);
|
||||
|
||||
/**
|
||||
* Enlarge wasm memory data space.
|
||||
*
|
||||
* @param module the wasm module instance
|
||||
* @param inc_page_count denote the page number to increase
|
||||
* @return return true if enlarge successfully, false otherwise
|
||||
*/
|
||||
bool
|
||||
wasm_runtime_enlarge_memory(WASMModuleInstanceCommon *module,
|
||||
uint32 inc_page_count);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
WASM_RUNTIME_API_EXTERN bool
|
||||
wasm_runtime_register_natives(const char *module_name,
|
||||
|
@ -900,6 +889,16 @@ wasm_runtime_dump_module_inst_mem_consumption(
|
|||
void
|
||||
wasm_runtime_dump_exec_env_mem_consumption(const WASMExecEnv *exec_env);
|
||||
|
||||
bool
|
||||
wasm_runtime_get_table_elem_type(const WASMModuleCommon *module_comm,
|
||||
uint32 table_idx, uint8 *out_elem_type,
|
||||
uint32 *out_min_size, uint32 *out_max_size);
|
||||
|
||||
bool
|
||||
wasm_runtime_get_table_inst_elem_type(
|
||||
const WASMModuleInstanceCommon *module_inst_comm, uint32 table_idx,
|
||||
uint8 *out_elem_type, uint32 *out_min_size, uint32 *out_max_size);
|
||||
|
||||
bool
|
||||
wasm_runtime_get_export_func_type(const WASMModuleCommon *module_comm,
|
||||
const WASMExport *export_, WASMType **out);
|
||||
|
|
|
@ -314,44 +314,26 @@ uint32
|
|||
wasm_runtime_atomic_wait(WASMModuleInstanceCommon *module, void *address,
|
||||
uint64 expect, int64 timeout, bool wait64)
|
||||
{
|
||||
WASMModuleInstance *module_inst = (WASMModuleInstance *)module;
|
||||
AtomicWaitInfo *wait_info;
|
||||
AtomicWaitNode *wait_node;
|
||||
bool check_ret, is_timeout;
|
||||
|
||||
#if WASM_ENABLE_INTERP != 0
|
||||
if (module->module_type == Wasm_Module_Bytecode) {
|
||||
WASMModuleInstance *module_inst = (WASMModuleInstance *)module;
|
||||
/* Currently we have only one memory instance */
|
||||
if (!module_inst->memories[0]->is_shared) {
|
||||
wasm_runtime_set_exception(module, "expected shared memory");
|
||||
return -1;
|
||||
}
|
||||
if ((uint8 *)address < module_inst->memories[0]->memory_data
|
||||
|| (uint8 *)address + (wait64 ? 8 : 4)
|
||||
> module_inst->memories[0]->memory_data_end) {
|
||||
wasm_runtime_set_exception(module, "out of bounds memory access");
|
||||
return -1;
|
||||
}
|
||||
bh_assert(module->module_type == Wasm_Module_Bytecode
|
||||
|| module->module_type == Wasm_Module_AoT);
|
||||
|
||||
/* Currently we have only one memory instance */
|
||||
if (!module_inst->memories[0]->is_shared) {
|
||||
wasm_runtime_set_exception(module, "expected shared memory");
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
#if WASM_ENABLE_AOT != 0
|
||||
if (module->module_type == Wasm_Module_AoT) {
|
||||
AOTModuleInstance *aot_inst = (AOTModuleInstance *)module;
|
||||
AOTMemoryInstance *aot_memory =
|
||||
((AOTMemoryInstance **)aot_inst->memories.ptr)[0];
|
||||
/* Currently we have only one memory instance */
|
||||
if (!aot_memory->is_shared) {
|
||||
wasm_runtime_set_exception(module, "expected shared memory");
|
||||
return -1;
|
||||
}
|
||||
if ((uint8 *)address < (uint8 *)aot_memory->memory_data.ptr
|
||||
|| (uint8 *)address + (wait64 ? 8 : 4)
|
||||
> (uint8 *)aot_memory->memory_data_end.ptr) {
|
||||
wasm_runtime_set_exception(module, "out of bounds memory access");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((uint8 *)address < module_inst->memories[0]->memory_data
|
||||
|| (uint8 *)address + (wait64 ? 8 : 4)
|
||||
> module_inst->memories[0]->memory_data_end) {
|
||||
wasm_runtime_set_exception(module, "out of bounds memory access");
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* acquire the wait info, create new one if not exists */
|
||||
wait_info = acquire_wait_info(address, true);
|
||||
|
@ -433,33 +415,18 @@ uint32
|
|||
wasm_runtime_atomic_notify(WASMModuleInstanceCommon *module, void *address,
|
||||
uint32 count)
|
||||
{
|
||||
WASMModuleInstance *module_inst = (WASMModuleInstance *)module;
|
||||
uint32 notify_result;
|
||||
AtomicWaitInfo *wait_info;
|
||||
|
||||
#if WASM_ENABLE_INTERP != 0
|
||||
if (module->module_type == Wasm_Module_Bytecode) {
|
||||
WASMModuleInstance *module_inst = (WASMModuleInstance *)module;
|
||||
if ((uint8 *)address < module_inst->memories[0]->memory_data
|
||||
|| (uint8 *)address + 4
|
||||
> module_inst->memories[0]->memory_data_end) {
|
||||
wasm_runtime_set_exception(module, "out of bounds memory access");
|
||||
return -1;
|
||||
}
|
||||
bh_assert(module->module_type == Wasm_Module_Bytecode
|
||||
|| module->module_type == Wasm_Module_AoT);
|
||||
|
||||
if ((uint8 *)address < module_inst->memories[0]->memory_data
|
||||
|| (uint8 *)address + 4 > module_inst->memories[0]->memory_data_end) {
|
||||
wasm_runtime_set_exception(module, "out of bounds memory access");
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
#if WASM_ENABLE_AOT != 0
|
||||
if (module->module_type == Wasm_Module_AoT) {
|
||||
AOTModuleInstance *aot_inst = (AOTModuleInstance *)module;
|
||||
AOTMemoryInstance *aot_memory =
|
||||
((AOTMemoryInstance **)aot_inst->memories.ptr)[0];
|
||||
if ((uint8 *)address < (uint8 *)aot_memory->memory_data.ptr
|
||||
|| (uint8 *)address + 4
|
||||
> (uint8 *)aot_memory->memory_data_end.ptr) {
|
||||
wasm_runtime_set_exception(module, "out of bounds memory access");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
wait_info = acquire_wait_info(address, false);
|
||||
|
||||
|
|
|
@ -304,14 +304,22 @@ aot_set_last_error_v(const char *format, ...);
|
|||
#endif
|
||||
|
||||
static inline uint32
|
||||
aot_get_tbl_data_slots(const AOTTable *tbl)
|
||||
aot_get_imp_tbl_data_slots(const AOTImportTable *tbl, bool is_jit_mode)
|
||||
{
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
if (is_jit_mode)
|
||||
return tbl->table_max_size;
|
||||
#endif
|
||||
return tbl->possible_grow ? tbl->table_max_size : tbl->table_init_size;
|
||||
}
|
||||
|
||||
static inline uint32
|
||||
aot_get_imp_tbl_data_slots(const AOTImportTable *tbl)
|
||||
aot_get_tbl_data_slots(const AOTTable *tbl, bool is_jit_mode)
|
||||
{
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
if (is_jit_mode)
|
||||
return tbl->table_max_size;
|
||||
#endif
|
||||
return tbl->possible_grow ? tbl->table_max_size : tbl->table_init_size;
|
||||
}
|
||||
|
||||
|
|
|
@ -211,6 +211,7 @@ aot_compile_func(AOTCompContext *comp_ctx, uint32 func_index)
|
|||
case WASM_OP_BLOCK:
|
||||
case WASM_OP_LOOP:
|
||||
case WASM_OP_IF:
|
||||
{
|
||||
value_type = *frame_ip++;
|
||||
if (value_type == VALUE_TYPE_I32 || value_type == VALUE_TYPE_I64
|
||||
|| value_type == VALUE_TYPE_F32
|
||||
|
@ -245,6 +246,25 @@ aot_compile_func(AOTCompContext *comp_ctx, uint32 func_index)
|
|||
param_count, param_types, result_count, result_types))
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
case EXT_OP_BLOCK:
|
||||
case EXT_OP_LOOP:
|
||||
case EXT_OP_IF:
|
||||
{
|
||||
read_leb_uint32(frame_ip, frame_ip_end, type_index);
|
||||
func_type = comp_ctx->comp_data->func_types[type_index];
|
||||
param_count = func_type->param_count;
|
||||
param_types = func_type->types;
|
||||
result_count = func_type->result_count;
|
||||
result_types = func_type->types + param_count;
|
||||
if (!aot_compile_op_block(
|
||||
comp_ctx, func_ctx, &frame_ip, frame_ip_end,
|
||||
(uint32)(LABEL_TYPE_BLOCK + opcode - EXT_OP_BLOCK),
|
||||
param_count, param_types, result_count, result_types))
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
case WASM_OP_ELSE:
|
||||
if (!aot_compile_op_else(comp_ctx, func_ctx, &frame_ip))
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
*/
|
||||
|
||||
#include "aot_emit_const.h"
|
||||
#include "aot_intrinsic.h"
|
||||
#include "../aot/aot_intrinsic.h"
|
||||
|
||||
bool
|
||||
aot_compile_op_i32_const(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
*/
|
||||
|
||||
#include "aot_emit_exception.h"
|
||||
#include "../interpreter/wasm_runtime.h"
|
||||
#include "../aot/aot_runtime.h"
|
||||
|
||||
bool
|
||||
|
@ -57,7 +58,7 @@ aot_emit_exception(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
}
|
||||
/* Create LLVM function with const function pointer */
|
||||
if (!(func_const =
|
||||
I64_CONST((uint64)(uintptr_t)aot_set_exception_with_id))
|
||||
I64_CONST((uint64)(uintptr_t)jit_set_exception_with_id))
|
||||
|| !(func = LLVMConstIntToPtr(func_const, func_ptr_type))) {
|
||||
aot_set_last_error("create LLVM value failed.");
|
||||
return false;
|
||||
|
|
|
@ -162,7 +162,7 @@ call_aot_invoke_native_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
}
|
||||
|
||||
/* JIT mode, call the function directly */
|
||||
if (!(func = I64_CONST((uint64)(uintptr_t)aot_invoke_native))
|
||||
if (!(func = I64_CONST((uint64)(uintptr_t)llvm_jit_invoke_native))
|
||||
|| !(func = LLVMConstIntToPtr(func, func_ptr_type))) {
|
||||
aot_set_last_error("create LLVM value failed.");
|
||||
return false;
|
||||
|
@ -407,7 +407,10 @@ call_aot_alloc_frame_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
param_types[1] = I32_TYPE;
|
||||
ret_type = INT8_TYPE;
|
||||
|
||||
GET_AOT_FUNCTION(aot_alloc_frame, 2);
|
||||
if (comp_ctx->is_jit_mode)
|
||||
GET_AOT_FUNCTION(llvm_jit_alloc_frame, 2);
|
||||
else
|
||||
GET_AOT_FUNCTION(aot_alloc_frame, 2);
|
||||
|
||||
param_values[0] = func_ctx->exec_env;
|
||||
param_values[1] = func_idx;
|
||||
|
@ -461,7 +464,10 @@ call_aot_free_frame_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
|
|||
param_types[0] = comp_ctx->exec_env_type;
|
||||
ret_type = INT8_TYPE;
|
||||
|
||||
GET_AOT_FUNCTION(aot_free_frame, 1);
|
||||
if (comp_ctx->is_jit_mode)
|
||||
GET_AOT_FUNCTION(llvm_jit_free_frame, 1);
|
||||
else
|
||||
GET_AOT_FUNCTION(aot_free_frame, 1);
|
||||
|
||||
param_values[0] = func_ctx->exec_env;
|
||||
|
||||
|
@ -557,7 +563,7 @@ check_app_addr_and_convert(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
|
||||
/* JIT mode, call the function directly */
|
||||
if (!(func =
|
||||
I64_CONST((uint64)(uintptr_t)aot_check_app_addr_and_convert))
|
||||
I64_CONST((uint64)(uintptr_t)jit_check_app_addr_and_convert))
|
||||
|| !(func = LLVMConstIntToPtr(func, func_ptr_type))) {
|
||||
aot_set_last_error("create LLVM value failed.");
|
||||
return false;
|
||||
|
@ -1047,7 +1053,7 @@ call_aot_call_indirect_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
}
|
||||
|
||||
/* JIT mode, call the function directly */
|
||||
if (!(func = I64_CONST((uint64)(uintptr_t)aot_call_indirect))
|
||||
if (!(func = I64_CONST((uint64)(uintptr_t)llvm_jit_call_indirect))
|
||||
|| !(func = LLVMConstIntToPtr(func, func_ptr_type))) {
|
||||
aot_set_last_error("create LLVM value failed.");
|
||||
return false;
|
||||
|
@ -1265,7 +1271,7 @@ aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
|
||||
/* load data as i32* */
|
||||
if (!(offset = I32_CONST(get_tbl_inst_offset(comp_ctx, func_ctx, tbl_idx)
|
||||
+ offsetof(AOTTableInstance, data)))) {
|
||||
+ offsetof(AOTTableInstance, elems)))) {
|
||||
HANDLE_FAILURE("LLVMConstInt");
|
||||
goto fail;
|
||||
}
|
||||
|
|
|
@ -718,7 +718,7 @@ aot_compile_op_memory_grow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
|
|||
aot_set_last_error("llvm add pointer type failed.");
|
||||
return false;
|
||||
}
|
||||
if (!(value = I64_CONST((uint64)(uintptr_t)aot_enlarge_memory))
|
||||
if (!(value = I64_CONST((uint64)(uintptr_t)wasm_enlarge_memory))
|
||||
|| !(func = LLVMConstIntToPtr(value, func_ptr_type))) {
|
||||
aot_set_last_error("create LLVM value failed.");
|
||||
return false;
|
||||
|
@ -899,7 +899,10 @@ aot_compile_op_memory_init(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
param_types[4] = I32_TYPE;
|
||||
ret_type = INT8_TYPE;
|
||||
|
||||
GET_AOT_FUNCTION(aot_memory_init, 5);
|
||||
if (comp_ctx->is_jit_mode)
|
||||
GET_AOT_FUNCTION(llvm_jit_memory_init, 5);
|
||||
else
|
||||
GET_AOT_FUNCTION(aot_memory_init, 5);
|
||||
|
||||
/* Call function aot_memory_init() */
|
||||
param_values[0] = func_ctx->aot_inst;
|
||||
|
@ -955,7 +958,10 @@ aot_compile_op_data_drop(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
param_types[1] = I32_TYPE;
|
||||
ret_type = INT8_TYPE;
|
||||
|
||||
GET_AOT_FUNCTION(aot_data_drop, 2);
|
||||
if (comp_ctx->is_jit_mode)
|
||||
GET_AOT_FUNCTION(llvm_jit_data_drop, 2);
|
||||
else
|
||||
GET_AOT_FUNCTION(aot_data_drop, 2);
|
||||
|
||||
/* Call function aot_data_drop() */
|
||||
param_values[0] = func_ctx->aot_inst;
|
||||
|
@ -971,6 +977,14 @@ fail:
|
|||
return false;
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_LAZY_JIT != 0
|
||||
static void *
|
||||
jit_memmove(void *dest, const void *src, size_t n)
|
||||
{
|
||||
return memmove(dest, src, n);
|
||||
}
|
||||
#endif
|
||||
|
||||
bool
|
||||
aot_compile_op_memory_copy(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
|
||||
{
|
||||
|
@ -1025,7 +1039,7 @@ aot_compile_op_memory_copy(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
|
|||
return false;
|
||||
}
|
||||
#else
|
||||
if (!(func = I64_CONST((uint64)(uintptr_t)aot_memmove))
|
||||
if (!(func = I64_CONST((uint64)(uintptr_t)jit_memmove))
|
||||
|| !(func = LLVMConstIntToPtr(func, func_ptr_type))) {
|
||||
aot_set_last_error("create LLVM value failed.");
|
||||
return false;
|
||||
|
@ -1054,6 +1068,12 @@ fail:
|
|||
return false;
|
||||
}
|
||||
|
||||
static void *
|
||||
jit_memset(void *s, int c, size_t n)
|
||||
{
|
||||
return memset(s, c, n);
|
||||
}
|
||||
|
||||
bool
|
||||
aot_compile_op_memory_fill(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
|
||||
{
|
||||
|
@ -1084,7 +1104,7 @@ aot_compile_op_memory_fill(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
|
|||
}
|
||||
|
||||
if (comp_ctx->is_jit_mode) {
|
||||
if (!(func = I64_CONST((uint64)(uintptr_t)aot_memset))
|
||||
if (!(func = I64_CONST((uint64)(uintptr_t)jit_memset))
|
||||
|| !(func = LLVMConstIntToPtr(func, func_ptr_type))) {
|
||||
aot_set_last_error("create LLVM value failed.");
|
||||
return false;
|
||||
|
|
|
@ -15,16 +15,25 @@ get_tbl_inst_offset(const AOTCompContext *comp_ctx,
|
|||
AOTImportTable *imp_tbls = comp_ctx->comp_data->import_tables;
|
||||
AOTTable *tbls = comp_ctx->comp_data->tables;
|
||||
|
||||
/* from the head of AOTModuleInstance */
|
||||
offset =
|
||||
offsetof(AOTModuleInstance, global_table_data.bytes)
|
||||
+ (uint64)comp_ctx->comp_data->memory_count * sizeof(AOTMemoryInstance)
|
||||
+ comp_ctx->comp_data->global_data_size;
|
||||
if (comp_ctx->is_jit_mode) {
|
||||
offset = offsetof(WASMModuleInstance, global_table_data.bytes)
|
||||
+ (uint64)comp_ctx->comp_data->memory_count
|
||||
* sizeof(AOTMemoryInstance)
|
||||
+ comp_ctx->comp_data->global_data_size;
|
||||
}
|
||||
else {
|
||||
offset = offsetof(AOTModuleInstance, global_table_data.bytes)
|
||||
+ (uint64)comp_ctx->comp_data->memory_count
|
||||
* sizeof(AOTMemoryInstance)
|
||||
+ comp_ctx->comp_data->global_data_size;
|
||||
}
|
||||
|
||||
while (i < tbl_idx && i < comp_ctx->comp_data->import_table_count) {
|
||||
offset += offsetof(AOTTableInstance, data);
|
||||
offset += offsetof(AOTTableInstance, elems);
|
||||
/* avoid loading from current AOTTableInstance */
|
||||
offset += sizeof(uint32) * aot_get_imp_tbl_data_slots(imp_tbls + i);
|
||||
offset +=
|
||||
sizeof(uint32)
|
||||
* aot_get_imp_tbl_data_slots(imp_tbls + i, comp_ctx->is_jit_mode);
|
||||
++i;
|
||||
}
|
||||
|
||||
|
@ -35,9 +44,10 @@ get_tbl_inst_offset(const AOTCompContext *comp_ctx,
|
|||
tbl_idx -= comp_ctx->comp_data->import_table_count;
|
||||
i -= comp_ctx->comp_data->import_table_count;
|
||||
while (i < tbl_idx && i < comp_ctx->comp_data->table_count) {
|
||||
offset += offsetof(AOTTableInstance, data);
|
||||
offset += offsetof(AOTTableInstance, elems);
|
||||
/* avoid loading from current AOTTableInstance */
|
||||
offset += sizeof(uint32) * aot_get_tbl_data_slots(tbls + i);
|
||||
offset += sizeof(uint32)
|
||||
* aot_get_tbl_data_slots(tbls + i, comp_ctx->is_jit_mode);
|
||||
++i;
|
||||
}
|
||||
|
||||
|
@ -82,7 +92,10 @@ aot_compile_op_elem_drop(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
param_types[1] = I32_TYPE;
|
||||
ret_type = VOID_TYPE;
|
||||
|
||||
GET_AOT_FUNCTION(aot_drop_table_seg, 2);
|
||||
if (comp_ctx->is_jit_mode)
|
||||
GET_AOT_FUNCTION(llvm_jit_drop_table_seg, 2);
|
||||
else
|
||||
GET_AOT_FUNCTION(aot_drop_table_seg, 2);
|
||||
|
||||
param_values[0] = func_ctx->aot_inst;
|
||||
if (!(param_values[1] = I32_CONST(tbl_seg_idx))) {
|
||||
|
@ -176,7 +189,7 @@ aot_compile_op_table_get(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
|
||||
/* load data as i32* */
|
||||
if (!(offset = I32_CONST(get_tbl_inst_offset(comp_ctx, func_ctx, tbl_idx)
|
||||
+ offsetof(AOTTableInstance, data)))) {
|
||||
+ offsetof(AOTTableInstance, elems)))) {
|
||||
HANDLE_FAILURE("LLVMConstInt");
|
||||
goto fail;
|
||||
}
|
||||
|
@ -230,7 +243,7 @@ aot_compile_op_table_set(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
|
||||
/* load data as i32* */
|
||||
if (!(offset = I32_CONST(get_tbl_inst_offset(comp_ctx, func_ctx, tbl_idx)
|
||||
+ offsetof(AOTTableInstance, data)))) {
|
||||
+ offsetof(AOTTableInstance, elems)))) {
|
||||
HANDLE_FAILURE("LLVMConstInt");
|
||||
goto fail;
|
||||
}
|
||||
|
@ -282,7 +295,10 @@ aot_compile_op_table_init(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
param_types[5] = I32_TYPE;
|
||||
ret_type = VOID_TYPE;
|
||||
|
||||
GET_AOT_FUNCTION(aot_table_init, 6);
|
||||
if (comp_ctx->is_jit_mode)
|
||||
GET_AOT_FUNCTION(llvm_jit_table_init, 6);
|
||||
else
|
||||
GET_AOT_FUNCTION(aot_table_init, 6);
|
||||
|
||||
param_values[0] = func_ctx->aot_inst;
|
||||
|
||||
|
@ -330,7 +346,10 @@ aot_compile_op_table_copy(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
param_types[5] = I32_TYPE;
|
||||
ret_type = VOID_TYPE;
|
||||
|
||||
GET_AOT_FUNCTION(aot_table_copy, 6);
|
||||
if (comp_ctx->is_jit_mode)
|
||||
GET_AOT_FUNCTION(llvm_jit_table_copy, 6);
|
||||
else
|
||||
GET_AOT_FUNCTION(aot_table_copy, 6);
|
||||
|
||||
param_values[0] = func_ctx->aot_inst;
|
||||
|
||||
|
@ -414,7 +433,10 @@ aot_compile_op_table_grow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
param_types[3] = I32_TYPE;
|
||||
ret_type = I32_TYPE;
|
||||
|
||||
GET_AOT_FUNCTION(aot_table_grow, 4);
|
||||
if (comp_ctx->is_jit_mode)
|
||||
GET_AOT_FUNCTION(llvm_jit_table_grow, 4);
|
||||
else
|
||||
GET_AOT_FUNCTION(aot_table_grow, 4);
|
||||
|
||||
param_values[0] = func_ctx->aot_inst;
|
||||
|
||||
|
@ -455,7 +477,10 @@ aot_compile_op_table_fill(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
param_types[4] = I32_TYPE;
|
||||
ret_type = VOID_TYPE;
|
||||
|
||||
GET_AOT_FUNCTION(aot_table_fill, 5);
|
||||
if (comp_ctx->is_jit_mode)
|
||||
GET_AOT_FUNCTION(llvm_jit_table_fill, 5);
|
||||
else
|
||||
GET_AOT_FUNCTION(aot_table_fill, 5);
|
||||
|
||||
param_values[0] = func_ctx->aot_inst;
|
||||
|
||||
|
|
|
@ -114,14 +114,23 @@ compile_global(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
{
|
||||
AOTCompData *comp_data = comp_ctx->comp_data;
|
||||
uint32 import_global_count = comp_data->import_global_count;
|
||||
uint32 global_base_offset =
|
||||
offsetof(AOTModuleInstance, global_table_data.bytes)
|
||||
+ sizeof(AOTMemoryInstance) * comp_ctx->comp_data->memory_count;
|
||||
uint32 global_base_offset;
|
||||
uint32 global_offset;
|
||||
uint8 global_type;
|
||||
LLVMValueRef offset, global_ptr, global, res;
|
||||
LLVMTypeRef ptr_type = NULL;
|
||||
|
||||
if (comp_ctx->is_jit_mode) {
|
||||
global_base_offset =
|
||||
offsetof(WASMModuleInstance, global_table_data.bytes)
|
||||
+ sizeof(WASMMemoryInstance) * comp_ctx->comp_data->memory_count;
|
||||
}
|
||||
else {
|
||||
global_base_offset =
|
||||
offsetof(AOTModuleInstance, global_table_data.bytes)
|
||||
+ sizeof(AOTMemoryInstance) * comp_ctx->comp_data->memory_count;
|
||||
}
|
||||
|
||||
bh_assert(global_idx < import_global_count + comp_data->global_count);
|
||||
|
||||
if (global_idx < import_global_count) {
|
||||
|
|
|
@ -264,7 +264,7 @@ create_memory_info(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
return false;
|
||||
}
|
||||
/* memories[0]->memory_data */
|
||||
offset = I32_CONST(offsetof(AOTMemoryInstance, memory_data.ptr));
|
||||
offset = I32_CONST(offsetof(AOTMemoryInstance, memory_data));
|
||||
if (!(func_ctx->mem_info[0].mem_base_addr = LLVMBuildInBoundsGEP2(
|
||||
comp_ctx->builder, INT8_TYPE, shared_mem_addr, &offset, 1,
|
||||
"mem_base_addr_offset"))) {
|
||||
|
@ -292,15 +292,24 @@ create_memory_info(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
else
|
||||
#endif
|
||||
{
|
||||
offset = I32_CONST(offsetof(AOTModuleInstance, global_table_data)
|
||||
+ offsetof(AOTMemoryInstance, memory_data.ptr));
|
||||
uint32 offset_of_global_table_data;
|
||||
|
||||
if (comp_ctx->is_jit_mode)
|
||||
offset_of_global_table_data =
|
||||
offsetof(WASMModuleInstance, global_table_data);
|
||||
else
|
||||
offset_of_global_table_data =
|
||||
offsetof(AOTModuleInstance, global_table_data);
|
||||
|
||||
offset = I32_CONST(offset_of_global_table_data
|
||||
+ offsetof(AOTMemoryInstance, memory_data));
|
||||
if (!(func_ctx->mem_info[0].mem_base_addr = LLVMBuildInBoundsGEP2(
|
||||
comp_ctx->builder, INT8_TYPE, func_ctx->aot_inst, &offset, 1,
|
||||
"mem_base_addr_offset"))) {
|
||||
aot_set_last_error("llvm build in bounds gep failed");
|
||||
return false;
|
||||
}
|
||||
offset = I32_CONST(offsetof(AOTModuleInstance, global_table_data)
|
||||
offset = I32_CONST(offset_of_global_table_data
|
||||
+ offsetof(AOTMemoryInstance, cur_page_count));
|
||||
if (!(func_ctx->mem_info[0].mem_cur_page_count_addr =
|
||||
LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE,
|
||||
|
@ -309,7 +318,7 @@ create_memory_info(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
aot_set_last_error("llvm build in bounds gep failed");
|
||||
return false;
|
||||
}
|
||||
offset = I32_CONST(offsetof(AOTModuleInstance, global_table_data)
|
||||
offset = I32_CONST(offset_of_global_table_data
|
||||
+ offsetof(AOTMemoryInstance, memory_data_size));
|
||||
if (!(func_ctx->mem_info[0].mem_data_size_addr = LLVMBuildInBoundsGEP2(
|
||||
comp_ctx->builder, INT8_TYPE, func_ctx->aot_inst, &offset, 1,
|
||||
|
@ -379,7 +388,7 @@ create_memory_info(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
|
||||
/* Load memory bound check constants */
|
||||
offset = I32_CONST(offsetof(AOTMemoryInstance, mem_bound_check_1byte)
|
||||
- offsetof(AOTMemoryInstance, memory_data.ptr));
|
||||
- offsetof(AOTMemoryInstance, memory_data));
|
||||
if (!(func_ctx->mem_info[0].mem_bound_check_1byte =
|
||||
LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE, mem_info_base,
|
||||
&offset, 1, "bound_check_1byte_offset"))) {
|
||||
|
@ -405,7 +414,7 @@ create_memory_info(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
}
|
||||
|
||||
offset = I32_CONST(offsetof(AOTMemoryInstance, mem_bound_check_2bytes)
|
||||
- offsetof(AOTMemoryInstance, memory_data.ptr));
|
||||
- offsetof(AOTMemoryInstance, memory_data));
|
||||
if (!(func_ctx->mem_info[0].mem_bound_check_2bytes =
|
||||
LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE, mem_info_base,
|
||||
&offset, 1, "bound_check_2bytes_offset"))) {
|
||||
|
@ -431,7 +440,7 @@ create_memory_info(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
}
|
||||
|
||||
offset = I32_CONST(offsetof(AOTMemoryInstance, mem_bound_check_4bytes)
|
||||
- offsetof(AOTMemoryInstance, memory_data.ptr));
|
||||
- offsetof(AOTMemoryInstance, memory_data));
|
||||
if (!(func_ctx->mem_info[0].mem_bound_check_4bytes =
|
||||
LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE, mem_info_base,
|
||||
&offset, 1, "bound_check_4bytes_offset"))) {
|
||||
|
@ -457,7 +466,7 @@ create_memory_info(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
}
|
||||
|
||||
offset = I32_CONST(offsetof(AOTMemoryInstance, mem_bound_check_8bytes)
|
||||
- offsetof(AOTMemoryInstance, memory_data.ptr));
|
||||
- offsetof(AOTMemoryInstance, memory_data));
|
||||
if (!(func_ctx->mem_info[0].mem_bound_check_8bytes =
|
||||
LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE, mem_info_base,
|
||||
&offset, 1, "bound_check_8bytes_offset"))) {
|
||||
|
@ -483,7 +492,7 @@ create_memory_info(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
}
|
||||
|
||||
offset = I32_CONST(offsetof(AOTMemoryInstance, mem_bound_check_16bytes)
|
||||
- offsetof(AOTMemoryInstance, memory_data.ptr));
|
||||
- offsetof(AOTMemoryInstance, memory_data));
|
||||
if (!(func_ctx->mem_info[0].mem_bound_check_16bytes = LLVMBuildInBoundsGEP2(
|
||||
comp_ctx->builder, INT8_TYPE, mem_info_base, &offset, 1,
|
||||
"bound_check_16bytes_offset"))) {
|
||||
|
@ -533,7 +542,7 @@ create_func_type_indexes(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
|
|||
LLVMValueRef offset, func_type_indexes_ptr;
|
||||
LLVMTypeRef int32_ptr_type;
|
||||
|
||||
offset = I32_CONST(offsetof(AOTModuleInstance, func_type_indexes.ptr));
|
||||
offset = I32_CONST(offsetof(AOTModuleInstance, func_type_indexes));
|
||||
func_type_indexes_ptr =
|
||||
LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE, func_ctx->aot_inst,
|
||||
&offset, 1, "func_type_indexes_ptr");
|
||||
|
|
|
@ -338,8 +338,8 @@ aot_lookup_orcjit_func(LLVMOrcLLJITRef orc_lazyjit, void *module_inst,
|
|||
LLVMErrorRef error;
|
||||
LLVMOrcJITTargetAddress func_addr = 0;
|
||||
AOTModuleInstance *aot_inst = (AOTModuleInstance *)module_inst;
|
||||
AOTModule *aot_module = (AOTModule *)aot_inst->aot_module.ptr;
|
||||
void **func_ptrs = (void **)aot_inst->func_ptrs.ptr;
|
||||
AOTModule *aot_module = (AOTModule *)aot_inst->module;
|
||||
void **func_ptrs = aot_inst->func_ptrs;
|
||||
|
||||
/**
|
||||
* No need to lock the func_ptr[func_idx] here as it is basic
|
||||
|
|
|
@ -1200,7 +1200,7 @@ jit_compile_op_return(JitCompContext *cc, uint8 **p_frame_ip)
|
|||
bool
|
||||
jit_compile_op_unreachable(JitCompContext *cc, uint8 **p_frame_ip)
|
||||
{
|
||||
if (!jit_emit_exception(cc, JIT_EXCE_UNREACHABLE, JIT_OP_JMP, 0, NULL))
|
||||
if (!jit_emit_exception(cc, EXCE_UNREACHABLE, JIT_OP_JMP, 0, NULL))
|
||||
return false;
|
||||
|
||||
return handle_next_reachable_block(cc, p_frame_ip);
|
||||
|
|
|
@ -201,19 +201,19 @@ jit_compile_check_value_range(JitCompContext *cc, JitReg value, JitReg min_fp,
|
|||
goto fail;
|
||||
|
||||
GEN_INSN(CMP, cc->cmp_reg, nan_ret, NEW_CONST(I32, 1));
|
||||
if (!jit_emit_exception(cc, JIT_EXCE_INVALID_CONVERSION_TO_INTEGER,
|
||||
JIT_OP_BEQ, cc->cmp_reg, NULL))
|
||||
if (!jit_emit_exception(cc, EXCE_INVALID_CONVERSION_TO_INTEGER, JIT_OP_BEQ,
|
||||
cc->cmp_reg, NULL))
|
||||
goto fail;
|
||||
|
||||
/* If value is out of integer range, throw exception */
|
||||
GEN_INSN(CMP, cc->cmp_reg, min_fp, value);
|
||||
if (!jit_emit_exception(cc, JIT_EXCE_INTEGER_OVERFLOW, JIT_OP_BGES,
|
||||
cc->cmp_reg, NULL))
|
||||
if (!jit_emit_exception(cc, EXCE_INTEGER_OVERFLOW, JIT_OP_BGES, cc->cmp_reg,
|
||||
NULL))
|
||||
goto fail;
|
||||
|
||||
GEN_INSN(CMP, cc->cmp_reg, value, max_fp);
|
||||
if (!jit_emit_exception(cc, JIT_EXCE_INTEGER_OVERFLOW, JIT_OP_BGES,
|
||||
cc->cmp_reg, NULL))
|
||||
if (!jit_emit_exception(cc, EXCE_INTEGER_OVERFLOW, JIT_OP_BGES, cc->cmp_reg,
|
||||
NULL))
|
||||
goto fail;
|
||||
|
||||
return true;
|
||||
|
|
|
@ -14,7 +14,7 @@ jit_emit_exception(JitCompContext *cc, int32 exception_id, uint8 jit_opcode,
|
|||
JitIncomingInsn *incoming_insn;
|
||||
JitReg else_label;
|
||||
|
||||
bh_assert(exception_id < JIT_EXCE_NUM);
|
||||
bh_assert(exception_id < EXCE_NUM);
|
||||
|
||||
if (jit_opcode >= JIT_OP_BEQ && jit_opcode <= JIT_OP_BLEU) {
|
||||
bh_assert(cond_br_if == cc->cmp_reg);
|
||||
|
|
|
@ -9,10 +9,6 @@
|
|||
#include "../jit_codegen.h"
|
||||
#include "../../interpreter/wasm_runtime.h"
|
||||
|
||||
extern bool
|
||||
jit_invoke_native(WASMExecEnv *exec_env, uint32 func_idx,
|
||||
WASMInterpFrame *prev_frame);
|
||||
|
||||
/* Prepare parameters for the function to call */
|
||||
static bool
|
||||
pre_call(JitCompContext *cc, const WASMType *func_type)
|
||||
|
@ -187,8 +183,8 @@ jit_compile_op_call(JitCompContext *cc, uint32 func_idx, bool tail_call)
|
|||
arg_regs[1] = NEW_CONST(I32, func_idx);
|
||||
arg_regs[2] = cc->fp_reg;
|
||||
|
||||
if (!jit_emit_callnative(cc, jit_invoke_native, native_ret, arg_regs,
|
||||
3)) {
|
||||
if (!jit_emit_callnative(cc, fast_jit_invoke_native, native_ret,
|
||||
arg_regs, 3)) {
|
||||
return false;
|
||||
}
|
||||
/* Convert bool to uint32 */
|
||||
|
@ -196,7 +192,7 @@ jit_compile_op_call(JitCompContext *cc, uint32 func_idx, bool tail_call)
|
|||
|
||||
/* Check whether there is exception thrown */
|
||||
GEN_INSN(CMP, cc->cmp_reg, native_ret, NEW_CONST(I32, 0));
|
||||
if (!jit_emit_exception(cc, JIT_EXCE_ALREADY_THROWN, JIT_OP_BEQ,
|
||||
if (!jit_emit_exception(cc, EXCE_ALREADY_THROWN, JIT_OP_BEQ,
|
||||
cc->cmp_reg, NULL)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -355,7 +351,8 @@ jit_compile_op_call_indirect(JitCompContext *cc, uint32 type_idx,
|
|||
arg_regs[4] = NEW_CONST(I32, func_type->param_cell_num);
|
||||
arg_regs[5] = argv;
|
||||
|
||||
if (!jit_emit_callnative(cc, jit_call_indirect, native_ret, arg_regs, 6)) {
|
||||
if (!jit_emit_callnative(cc, fast_jit_call_indirect, native_ret, arg_regs,
|
||||
6)) {
|
||||
return false;
|
||||
}
|
||||
/* Convert bool to uint32 */
|
||||
|
@ -363,8 +360,8 @@ jit_compile_op_call_indirect(JitCompContext *cc, uint32 type_idx,
|
|||
|
||||
/* Check whether there is exception thrown */
|
||||
GEN_INSN(CMP, cc->cmp_reg, native_ret, NEW_CONST(I32, 0));
|
||||
if (!jit_emit_exception(cc, JIT_EXCE_ALREADY_THROWN, JIT_OP_BEQ,
|
||||
cc->cmp_reg, NULL)) {
|
||||
if (!jit_emit_exception(cc, EXCE_ALREADY_THROWN, JIT_OP_BEQ, cc->cmp_reg,
|
||||
NULL)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -78,8 +78,8 @@ check_and_seek_on_64bit_platform(JitCompContext *cc, JitReg addr, JitReg offset,
|
|||
#ifndef OS_ENABLE_HW_BOUND_CHECK
|
||||
/* if (offset1 > memory_boundary) goto EXCEPTION */
|
||||
GEN_INSN(CMP, cc->cmp_reg, offset1, memory_boundary);
|
||||
if (!jit_emit_exception(cc, JIT_EXCE_OUT_OF_BOUNDS_MEMORY_ACCESS,
|
||||
JIT_OP_BGTU, cc->cmp_reg, NULL)) {
|
||||
if (!jit_emit_exception(cc, EXCE_OUT_OF_BOUNDS_MEMORY_ACCESS, JIT_OP_BGTU,
|
||||
cc->cmp_reg, NULL)) {
|
||||
goto fail;
|
||||
}
|
||||
#endif
|
||||
|
@ -103,16 +103,16 @@ check_and_seek_on_32bit_platform(JitCompContext *cc, JitReg addr, JitReg offset,
|
|||
|
||||
/* if (offset1 < addr) goto EXCEPTION */
|
||||
GEN_INSN(CMP, cc->cmp_reg, offset1, addr);
|
||||
if (!jit_emit_exception(cc, JIT_EXCE_OUT_OF_BOUNDS_MEMORY_ACCESS,
|
||||
JIT_OP_BLTU, cc->cmp_reg, NULL)) {
|
||||
if (!jit_emit_exception(cc, EXCE_OUT_OF_BOUNDS_MEMORY_ACCESS, JIT_OP_BLTU,
|
||||
cc->cmp_reg, NULL)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
#ifndef OS_ENABLE_HW_BOUND_CHECK
|
||||
/* if (offset1 > memory_boundary) goto EXCEPTION */
|
||||
GEN_INSN(CMP, cc->cmp_reg, offset1, memory_boundary);
|
||||
if (!jit_emit_exception(cc, JIT_EXCE_OUT_OF_BOUNDS_MEMORY_ACCESS,
|
||||
JIT_OP_BGTU, cc->cmp_reg, NULL)) {
|
||||
if (!jit_emit_exception(cc, EXCE_OUT_OF_BOUNDS_MEMORY_ACCESS, JIT_OP_BGTU,
|
||||
cc->cmp_reg, NULL)) {
|
||||
goto fail;
|
||||
}
|
||||
#endif
|
||||
|
@ -144,7 +144,7 @@ check_and_seek(JitCompContext *cc, JitReg addr, uint32 offset, uint32 bytes)
|
|||
GEN_INSN(LDI32, cur_mem_page_count, memory_inst,
|
||||
NEW_CONST(I32, offsetof(WASMMemoryInstance, cur_page_count)));
|
||||
GEN_INSN(CMP, cc->cmp_reg, cur_mem_page_count, NEW_CONST(I32, 0));
|
||||
if (!jit_emit_exception(cc, JIT_EXCE_OUT_OF_BOUNDS_MEMORY_ACCESS,
|
||||
if (!jit_emit_exception(cc, EXCE_OUT_OF_BOUNDS_MEMORY_ACCESS,
|
||||
JIT_OP_BEQ, cc->cmp_reg, NULL)) {
|
||||
goto fail;
|
||||
}
|
||||
|
@ -604,8 +604,8 @@ jit_compile_op_memory_init(JitCompContext *cc, uint32 mem_idx, uint32 seg_idx)
|
|||
goto fail;
|
||||
|
||||
GEN_INSN(CMP, cc->cmp_reg, res, NEW_CONST(I32, 0));
|
||||
if (!jit_emit_exception(cc, JIT_EXCE_ALREADY_THROWN, JIT_OP_BLTS,
|
||||
cc->cmp_reg, NULL))
|
||||
if (!jit_emit_exception(cc, EXCE_ALREADY_THROWN, JIT_OP_BLTS, cc->cmp_reg,
|
||||
NULL))
|
||||
goto fail;
|
||||
|
||||
return true;
|
||||
|
@ -687,8 +687,8 @@ jit_compile_op_memory_copy(JitCompContext *cc, uint32 src_mem_idx,
|
|||
goto fail;
|
||||
|
||||
GEN_INSN(CMP, cc->cmp_reg, res, NEW_CONST(I32, 0));
|
||||
if (!jit_emit_exception(cc, JIT_EXCE_ALREADY_THROWN, JIT_OP_BLTS,
|
||||
cc->cmp_reg, NULL))
|
||||
if (!jit_emit_exception(cc, EXCE_ALREADY_THROWN, JIT_OP_BLTS, cc->cmp_reg,
|
||||
NULL))
|
||||
goto fail;
|
||||
|
||||
return true;
|
||||
|
@ -741,8 +741,8 @@ jit_compile_op_memory_fill(JitCompContext *cc, uint32 mem_idx)
|
|||
goto fail;
|
||||
|
||||
GEN_INSN(CMP, cc->cmp_reg, res, NEW_CONST(I32, 0));
|
||||
if (!jit_emit_exception(cc, JIT_EXCE_ALREADY_THROWN, JIT_OP_BLTS,
|
||||
cc->cmp_reg, NULL))
|
||||
if (!jit_emit_exception(cc, EXCE_ALREADY_THROWN, JIT_OP_BLTS, cc->cmp_reg,
|
||||
NULL))
|
||||
goto fail;
|
||||
|
||||
return true;
|
||||
|
|
|
@ -665,7 +665,7 @@ compile_int_div(JitCompContext *cc, IntArithmetic arith_op, bool is_i32,
|
|||
case 0:
|
||||
{
|
||||
/* Directly throw exception if divided by zero */
|
||||
if (!(jit_emit_exception(cc, JIT_EXCE_INTEGER_DIVIDE_BY_ZERO,
|
||||
if (!(jit_emit_exception(cc, EXCE_INTEGER_DIVIDE_BY_ZERO,
|
||||
JIT_OP_JMP, 0, NULL)))
|
||||
goto fail;
|
||||
|
||||
|
@ -699,7 +699,7 @@ compile_int_div(JitCompContext *cc, IntArithmetic arith_op, bool is_i32,
|
|||
|
||||
/* Throw integer overflow exception if left is
|
||||
INT32_MIN or INT64_MIN */
|
||||
if (!(jit_emit_exception(cc, JIT_EXCE_INTEGER_OVERFLOW,
|
||||
if (!(jit_emit_exception(cc, EXCE_INTEGER_OVERFLOW,
|
||||
JIT_OP_BEQ, cc->cmp_reg, NULL)))
|
||||
goto fail;
|
||||
|
||||
|
@ -739,8 +739,8 @@ compile_int_div(JitCompContext *cc, IntArithmetic arith_op, bool is_i32,
|
|||
GEN_INSN(CMP, cc->cmp_reg, right,
|
||||
is_i32 ? NEW_CONST(I32, 0) : NEW_CONST(I64, 0));
|
||||
/* Throw integer divided by zero exception if right is zero */
|
||||
if (!(jit_emit_exception(cc, JIT_EXCE_INTEGER_DIVIDE_BY_ZERO,
|
||||
JIT_OP_BEQ, cc->cmp_reg, NULL)))
|
||||
if (!(jit_emit_exception(cc, EXCE_INTEGER_DIVIDE_BY_ZERO, JIT_OP_BEQ,
|
||||
cc->cmp_reg, NULL)))
|
||||
goto fail;
|
||||
|
||||
switch (arith_op) {
|
||||
|
@ -760,8 +760,8 @@ compile_int_div(JitCompContext *cc, IntArithmetic arith_op, bool is_i32,
|
|||
GEN_INSN(CMP, cc->cmp_reg, cmp1, NEW_CONST(I32, 1));
|
||||
/* Throw integer overflow exception if left is INT32_MIN or
|
||||
INT64_MIN, and right is -1 */
|
||||
if (!(jit_emit_exception(cc, JIT_EXCE_INTEGER_OVERFLOW,
|
||||
JIT_OP_BEQ, cc->cmp_reg, NULL)))
|
||||
if (!(jit_emit_exception(cc, EXCE_INTEGER_OVERFLOW, JIT_OP_BEQ,
|
||||
cc->cmp_reg, NULL)))
|
||||
goto fail;
|
||||
|
||||
/* Build default div and rem */
|
||||
|
|
|
@ -37,8 +37,8 @@ jit_compile_op_table_get(JitCompContext *cc, uint32 tbl_idx)
|
|||
/* if (elem_idx >= tbl_sz) goto exception; */
|
||||
tbl_sz = get_table_cur_size_reg(cc->jit_frame, tbl_idx);
|
||||
GEN_INSN(CMP, cc->cmp_reg, elem_idx, tbl_sz);
|
||||
if (!jit_emit_exception(cc, JIT_EXCE_OUT_OF_BOUNDS_TABLE_ACCESS,
|
||||
JIT_OP_BGEU, cc->cmp_reg, NULL))
|
||||
if (!jit_emit_exception(cc, EXCE_OUT_OF_BOUNDS_TABLE_ACCESS, JIT_OP_BGEU,
|
||||
cc->cmp_reg, NULL))
|
||||
goto fail;
|
||||
|
||||
elem_idx_long = jit_cc_new_reg_I64(cc);
|
||||
|
@ -68,8 +68,8 @@ jit_compile_op_table_set(JitCompContext *cc, uint32 tbl_idx)
|
|||
/* if (elem_idx >= tbl_sz) goto exception; */
|
||||
tbl_sz = get_table_cur_size_reg(cc->jit_frame, tbl_idx);
|
||||
GEN_INSN(CMP, cc->cmp_reg, elem_idx, tbl_sz);
|
||||
if (!jit_emit_exception(cc, JIT_EXCE_OUT_OF_BOUNDS_TABLE_ACCESS,
|
||||
JIT_OP_BGEU, cc->cmp_reg, NULL))
|
||||
if (!jit_emit_exception(cc, EXCE_OUT_OF_BOUNDS_TABLE_ACCESS, JIT_OP_BGEU,
|
||||
cc->cmp_reg, NULL))
|
||||
goto fail;
|
||||
|
||||
elem_idx_long = jit_cc_new_reg_I64(cc);
|
||||
|
@ -105,7 +105,7 @@ wasm_init_table(WASMModuleInstance *inst, uint32 tbl_idx, uint32 elem_idx,
|
|||
if (src > elem_len || elem_len - src < len)
|
||||
goto out_of_bounds;
|
||||
|
||||
bh_memcpy_s((uint8 *)(tbl) + offsetof(WASMTableInstance, base_addr)
|
||||
bh_memcpy_s((uint8 *)tbl + offsetof(WASMTableInstance, elems)
|
||||
+ dst * sizeof(uint32),
|
||||
(uint32)((tbl_sz - dst) * sizeof(uint32)),
|
||||
elem->func_indexes + src, (uint32)(len * sizeof(uint32)));
|
||||
|
@ -140,8 +140,8 @@ jit_compile_op_table_init(JitCompContext *cc, uint32 tbl_idx,
|
|||
goto fail;
|
||||
|
||||
GEN_INSN(CMP, cc->cmp_reg, res, NEW_CONST(I32, 0));
|
||||
if (!jit_emit_exception(cc, JIT_EXCE_ALREADY_THROWN, JIT_OP_BLTS,
|
||||
cc->cmp_reg, NULL))
|
||||
if (!jit_emit_exception(cc, EXCE_ALREADY_THROWN, JIT_OP_BLTS, cc->cmp_reg,
|
||||
NULL))
|
||||
goto fail;
|
||||
|
||||
return true;
|
||||
|
@ -167,10 +167,10 @@ wasm_copy_table(WASMModuleInstance *inst, uint32 src_tbl_idx,
|
|||
if (dst_offset > dst_tbl_sz || dst_tbl_sz - dst_offset < len)
|
||||
goto out_of_bounds;
|
||||
|
||||
bh_memmove_s((uint8 *)(dst_tbl) + offsetof(WASMTableInstance, base_addr)
|
||||
bh_memmove_s((uint8 *)dst_tbl + offsetof(WASMTableInstance, elems)
|
||||
+ dst_offset * sizeof(uint32),
|
||||
(uint32)((dst_tbl_sz - dst_offset) * sizeof(uint32)),
|
||||
(uint8 *)(src_tbl) + offsetof(WASMTableInstance, base_addr)
|
||||
(uint8 *)src_tbl + offsetof(WASMTableInstance, elems)
|
||||
+ src_offset * sizeof(uint32),
|
||||
(uint32)(len * sizeof(uint32)));
|
||||
|
||||
|
@ -204,8 +204,8 @@ jit_compile_op_table_copy(JitCompContext *cc, uint32 src_tbl_idx,
|
|||
goto fail;
|
||||
|
||||
GEN_INSN(CMP, cc->cmp_reg, res, NEW_CONST(I32, 0));
|
||||
if (!jit_emit_exception(cc, JIT_EXCE_ALREADY_THROWN, JIT_OP_BLTS,
|
||||
cc->cmp_reg, NULL))
|
||||
if (!jit_emit_exception(cc, EXCE_ALREADY_THROWN, JIT_OP_BLTS, cc->cmp_reg,
|
||||
NULL))
|
||||
goto fail;
|
||||
|
||||
return true;
|
||||
|
@ -276,7 +276,7 @@ wasm_fill_table(WASMModuleInstance *inst, uint32 tbl_idx, uint32 dst,
|
|||
goto out_of_bounds;
|
||||
|
||||
for (; len != 0; dst++, len--) {
|
||||
((uint32 *)(tbl->base_addr))[dst] = val;
|
||||
tbl->elems[dst] = val;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -307,8 +307,8 @@ jit_compile_op_table_fill(JitCompContext *cc, uint32 tbl_idx)
|
|||
goto fail;
|
||||
|
||||
GEN_INSN(CMP, cc->cmp_reg, res, NEW_CONST(I32, 0));
|
||||
if (!jit_emit_exception(cc, JIT_EXCE_ALREADY_THROWN, JIT_OP_BLTS,
|
||||
cc->cmp_reg, NULL))
|
||||
if (!jit_emit_exception(cc, EXCE_ALREADY_THROWN, JIT_OP_BLTS, cc->cmp_reg,
|
||||
NULL))
|
||||
goto fail;
|
||||
|
||||
return true;
|
||||
|
|
|
@ -277,11 +277,11 @@ jit_compile_op_set_global(JitCompContext *cc, uint32 global_idx,
|
|||
JitReg aux_stack_bottom =
|
||||
get_aux_stack_bottom_reg(cc->jit_frame);
|
||||
GEN_INSN(CMP, cc->cmp_reg, value, aux_stack_bound);
|
||||
if (!(jit_emit_exception(cc, JIT_EXCE_AUX_STACK_OVERFLOW,
|
||||
if (!(jit_emit_exception(cc, EXCE_AUX_STACK_OVERFLOW,
|
||||
JIT_OP_BLEU, cc->cmp_reg, NULL)))
|
||||
goto fail;
|
||||
GEN_INSN(CMP, cc->cmp_reg, value, aux_stack_bottom);
|
||||
if (!(jit_emit_exception(cc, JIT_EXCE_AUX_STACK_UNDERFLOW,
|
||||
if (!(jit_emit_exception(cc, EXCE_AUX_STACK_UNDERFLOW,
|
||||
JIT_OP_BGTU, cc->cmp_reg, NULL)))
|
||||
goto fail;
|
||||
}
|
||||
|
|
|
@ -18,31 +18,9 @@
|
|||
#include "fe/jit_emit_variable.h"
|
||||
#include "../interpreter/wasm_interp.h"
|
||||
#include "../interpreter/wasm_opcode.h"
|
||||
#include "../interpreter/wasm_runtime.h"
|
||||
#include "../common/wasm_exec_env.h"
|
||||
|
||||
/* clang-format off */
|
||||
static const char *jit_exception_msgs[] = {
|
||||
"unreachable", /* JIT_EXCE_UNREACHABLE */
|
||||
"allocate memory failed", /* JIT_EXCE_OUT_OF_MEMORY */
|
||||
"out of bounds memory access", /* JIT_EXCE_OUT_OF_BOUNDS_MEMORY_ACCESS */
|
||||
"integer overflow", /* JIT_EXCE_INTEGER_OVERFLOW */
|
||||
"integer divide by zero", /* JIT_EXCE_INTEGER_DIVIDE_BY_ZERO */
|
||||
"invalid conversion to integer", /* JIT_EXCE_INVALID_CONVERSION_TO_INTEGER */
|
||||
"indirect call type mismatch", /* JIT_EXCE_INVALID_FUNCTION_TYPE_INDEX */
|
||||
"invalid function index", /* JIT_EXCE_INVALID_FUNCTION_INDEX */
|
||||
"undefined element", /* JIT_EXCE_UNDEFINED_ELEMENT */
|
||||
"uninitialized element", /* JIT_EXCE_UNINITIALIZED_ELEMENT */
|
||||
"failed to call unlinked import function", /* JIT_EXCE_CALL_UNLINKED_IMPORT_FUNC */
|
||||
"native stack overflow", /* JIT_EXCE_NATIVE_STACK_OVERFLOW */
|
||||
"unaligned atomic", /* JIT_EXCE_UNALIGNED_ATOMIC */
|
||||
"wasm auxiliary stack overflow", /* JIT_EXCE_AUX_STACK_OVERFLOW */
|
||||
"wasm auxiliary stack underflow", /* JIT_EXCE_AUX_STACK_UNDERFLOW */
|
||||
"out of bounds table access", /* JIT_EXCE_OUT_OF_BOUNDS_TABLE_ACCESS */
|
||||
"wasm operand stack overflow", /* JIT_EXCE_OPERAND_STACK_OVERFLOW */
|
||||
"", /* JIT_EXCE_ALREADY_THROWN */
|
||||
};
|
||||
/* clang-format on */
|
||||
|
||||
JitReg
|
||||
get_module_inst_reg(JitFrame *frame)
|
||||
{
|
||||
|
@ -378,7 +356,7 @@ get_table_data_reg(JitFrame *frame, uint32 tbl_idx)
|
|||
frame->table_regs[tbl_idx].table_data =
|
||||
cc->table_regs[tbl_idx].table_data;
|
||||
GEN_INSN(ADD, frame->table_regs[tbl_idx].table_data, table_reg,
|
||||
NEW_CONST(I64, offsetof(WASMTableInstance, base_addr)));
|
||||
NEW_CONST(I64, offsetof(WASMTableInstance, elems)));
|
||||
}
|
||||
return frame->table_regs[tbl_idx].table_data;
|
||||
}
|
||||
|
@ -586,15 +564,6 @@ gen_commit_sp_ip(JitFrame *frame)
|
|||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
jit_set_exception_with_id(WASMModuleInstance *module_inst, uint32 id)
|
||||
{
|
||||
if (id < JIT_EXCE_NUM)
|
||||
wasm_set_exception(module_inst, jit_exception_msgs[id]);
|
||||
else
|
||||
wasm_set_exception(module_inst, "unknown exception");
|
||||
}
|
||||
|
||||
static bool
|
||||
create_fixed_virtual_regs(JitCompContext *cc)
|
||||
{
|
||||
|
@ -681,7 +650,7 @@ form_and_translate_func(JitCompContext *cc)
|
|||
jit_basic_block_append_insn(jit_cc_entry_basic_block(cc), insn);
|
||||
|
||||
/* Patch INSNs jumping to exception basic blocks. */
|
||||
for (i = 0; i < JIT_EXCE_NUM; i++) {
|
||||
for (i = 0; i < EXCE_NUM; i++) {
|
||||
incoming_insn = cc->incoming_insns_for_exec_bbs[i];
|
||||
if (incoming_insn) {
|
||||
if (!(cc->exce_basic_blocks[i] = jit_cc_new_basic_block(cc, 0))) {
|
||||
|
@ -703,7 +672,7 @@ form_and_translate_func(JitCompContext *cc)
|
|||
incoming_insn = incoming_insn_next;
|
||||
}
|
||||
cc->cur_basic_block = cc->exce_basic_blocks[i];
|
||||
if (i != JIT_EXCE_ALREADY_THROWN) {
|
||||
if (i != EXCE_ALREADY_THROWN) {
|
||||
JitReg module_inst_reg = jit_cc_new_reg_ptr(cc);
|
||||
GEN_INSN(LDPTR, module_inst_reg, cc->exec_env_reg,
|
||||
NEW_CONST(I32, offsetof(WASMExecEnv, module_inst)));
|
||||
|
@ -850,7 +819,7 @@ init_func_translation(JitCompContext *cc)
|
|||
GEN_INSN(ADD, frame_boundary, top, NEW_CONST(PTR, frame_size + outs_size));
|
||||
/* if frame_boundary > top_boundary, throw stack overflow exception */
|
||||
GEN_INSN(CMP, cc->cmp_reg, frame_boundary, top_boundary);
|
||||
if (!jit_emit_exception(cc, JIT_EXCE_OPERAND_STACK_OVERFLOW, JIT_OP_BGTU,
|
||||
if (!jit_emit_exception(cc, EXCE_OPERAND_STACK_OVERFLOW, JIT_OP_BGTU,
|
||||
cc->cmp_reg, NULL)) {
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -104,28 +104,6 @@ typedef enum FloatArithmetic {
|
|||
FLOAT_MAX,
|
||||
} FloatArithmetic;
|
||||
|
||||
typedef enum JitExceptionID {
|
||||
JIT_EXCE_UNREACHABLE = 0,
|
||||
JIT_EXCE_OUT_OF_MEMORY,
|
||||
JIT_EXCE_OUT_OF_BOUNDS_MEMORY_ACCESS,
|
||||
JIT_EXCE_INTEGER_OVERFLOW,
|
||||
JIT_EXCE_INTEGER_DIVIDE_BY_ZERO,
|
||||
JIT_EXCE_INVALID_CONVERSION_TO_INTEGER,
|
||||
JIT_EXCE_INVALID_FUNCTION_TYPE_INDEX,
|
||||
JIT_EXCE_INVALID_FUNCTION_INDEX,
|
||||
JIT_EXCE_UNDEFINED_ELEMENT,
|
||||
JIT_EXCE_UNINITIALIZED_ELEMENT,
|
||||
JIT_EXCE_CALL_UNLINKED_IMPORT_FUNC,
|
||||
JIT_EXCE_NATIVE_STACK_OVERFLOW,
|
||||
JIT_EXCE_UNALIGNED_ATOMIC,
|
||||
JIT_EXCE_AUX_STACK_OVERFLOW,
|
||||
JIT_EXCE_AUX_STACK_UNDERFLOW,
|
||||
JIT_EXCE_OUT_OF_BOUNDS_TABLE_ACCESS,
|
||||
JIT_EXCE_OPERAND_STACK_OVERFLOW,
|
||||
JIT_EXCE_ALREADY_THROWN,
|
||||
JIT_EXCE_NUM,
|
||||
} JitExceptionID;
|
||||
|
||||
/**
|
||||
* Translate instructions in a function. The translated block must
|
||||
* end with a branch instruction whose targets are offsets relating to
|
||||
|
|
|
@ -382,6 +382,7 @@ jit_cc_init(JitCompContext *cc, unsigned htab_size)
|
|||
blocks respectively. */
|
||||
if (!(entry_block = jit_cc_new_basic_block(cc, 0)))
|
||||
goto fail;
|
||||
|
||||
if (!(exit_block = jit_cc_new_basic_block(cc, 0))) {
|
||||
jit_basic_block_delete(entry_block);
|
||||
goto fail;
|
||||
|
@ -395,11 +396,11 @@ jit_cc_init(JitCompContext *cc, unsigned htab_size)
|
|||
&& jit_reg_no(cc->exit_label) == 1);
|
||||
|
||||
if (!(cc->exce_basic_blocks =
|
||||
jit_calloc(sizeof(JitBasicBlock *) * JIT_EXCE_NUM)))
|
||||
jit_calloc(sizeof(JitBasicBlock *) * EXCE_NUM)))
|
||||
goto fail;
|
||||
|
||||
if (!(cc->incoming_insns_for_exec_bbs =
|
||||
jit_calloc(sizeof(JitIncomingInsnList) * JIT_EXCE_NUM)))
|
||||
jit_calloc(sizeof(JitIncomingInsnList) * EXCE_NUM)))
|
||||
goto fail;
|
||||
|
||||
cc->hreg_info = jit_codegen_get_hreg_info();
|
||||
|
@ -465,7 +466,7 @@ jit_cc_destroy(JitCompContext *cc)
|
|||
jit_free(cc->exce_basic_blocks);
|
||||
|
||||
if (cc->incoming_insns_for_exec_bbs) {
|
||||
for (i = 0; i < JIT_EXCE_NUM; i++) {
|
||||
for (i = 0; i < EXCE_NUM; i++) {
|
||||
incoming_insn = cc->incoming_insns_for_exec_bbs[i];
|
||||
while (incoming_insn) {
|
||||
incoming_insn_next = incoming_insn->next;
|
||||
|
|
|
@ -461,7 +461,7 @@ WASM_API_EXTERN bool wasm_module_validate(wasm_store_t*, const wasm_byte_vec_t*
|
|||
WASM_API_EXTERN void wasm_module_imports(const wasm_module_t*, own wasm_importtype_vec_t* out);
|
||||
WASM_API_EXTERN void wasm_module_exports(const wasm_module_t*, own wasm_exporttype_vec_t* out);
|
||||
|
||||
WASM_API_EXTERN void wasm_module_serialize(const wasm_module_t*, own wasm_byte_vec_t* out);
|
||||
WASM_API_EXTERN void wasm_module_serialize(wasm_module_t*, own wasm_byte_vec_t* out);
|
||||
WASM_API_EXTERN own wasm_module_t* wasm_module_deserialize(wasm_store_t*, const wasm_byte_vec_t*);
|
||||
|
||||
|
||||
|
|
|
@ -263,6 +263,9 @@ struct WASMFunction {
|
|||
#if WASM_ENABLE_FAST_JIT != 0
|
||||
void *fast_jit_jitted_code;
|
||||
#endif
|
||||
#if WASM_ENABLE_JIT != 0
|
||||
void *llvm_jit_func_ptr;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct WASMGlobal {
|
||||
|
@ -363,6 +366,11 @@ typedef struct WASMCustomSection {
|
|||
} WASMCustomSection;
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_JIT != 0
|
||||
struct AOTCompData;
|
||||
struct AOTCompContext;
|
||||
#endif
|
||||
|
||||
struct WASMModule {
|
||||
/* Module type, for module loaded from WASM bytecode binary,
|
||||
this field is Wasm_Module_Bytecode;
|
||||
|
@ -407,6 +415,9 @@ struct WASMModule {
|
|||
WASMDataSeg **data_segments;
|
||||
uint32 start_function;
|
||||
|
||||
/* total global variable size */
|
||||
uint32 global_data_size;
|
||||
|
||||
/* the index of auxiliary __data_end global,
|
||||
-1 means unexported */
|
||||
uint32 aux_data_end_global_index;
|
||||
|
@ -493,6 +504,12 @@ struct WASMModule {
|
|||
/* point to JITed functions */
|
||||
void **fast_jit_func_ptrs;
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_JIT != 0
|
||||
struct AOTCompData *comp_data;
|
||||
struct AOTCompContext *comp_ctx;
|
||||
void **func_ptrs;
|
||||
#endif
|
||||
};
|
||||
|
||||
typedef struct BlockType {
|
||||
|
|
|
@ -641,28 +641,28 @@ trunc_f64_to_int(WASMModuleInstance *module, uint32 *frame_sp, float64 src_min,
|
|||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); \
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(); \
|
||||
\
|
||||
os_mutex_lock(&memory->mem_lock); \
|
||||
os_mutex_lock(&module->e->mem_lock); \
|
||||
readv = (uint32)(*(uint8 *)maddr); \
|
||||
*(uint8 *)maddr = (uint8)(readv op sval); \
|
||||
os_mutex_unlock(&memory->mem_lock); \
|
||||
os_mutex_unlock(&module->e->mem_lock); \
|
||||
} \
|
||||
else if (opcode == WASM_OP_ATOMIC_RMW_I32_##OP_NAME##16_U) { \
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); \
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(); \
|
||||
\
|
||||
os_mutex_lock(&memory->mem_lock); \
|
||||
os_mutex_lock(&module->e->mem_lock); \
|
||||
readv = (uint32)LOAD_U16(maddr); \
|
||||
STORE_U16(maddr, (uint16)(readv op sval)); \
|
||||
os_mutex_unlock(&memory->mem_lock); \
|
||||
os_mutex_unlock(&module->e->mem_lock); \
|
||||
} \
|
||||
else { \
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); \
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(); \
|
||||
\
|
||||
os_mutex_lock(&memory->mem_lock); \
|
||||
os_mutex_lock(&module->e->mem_lock); \
|
||||
readv = LOAD_I32(maddr); \
|
||||
STORE_U32(maddr, readv op sval); \
|
||||
os_mutex_unlock(&memory->mem_lock); \
|
||||
os_mutex_unlock(&module->e->mem_lock); \
|
||||
} \
|
||||
PUSH_I32(readv); \
|
||||
break; \
|
||||
|
@ -681,39 +681,39 @@ trunc_f64_to_int(WASMModuleInstance *module, uint32 *frame_sp, float64 src_min,
|
|||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); \
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(); \
|
||||
\
|
||||
os_mutex_lock(&memory->mem_lock); \
|
||||
os_mutex_lock(&module->e->mem_lock); \
|
||||
readv = (uint64)(*(uint8 *)maddr); \
|
||||
*(uint8 *)maddr = (uint8)(readv op sval); \
|
||||
os_mutex_unlock(&memory->mem_lock); \
|
||||
os_mutex_unlock(&module->e->mem_lock); \
|
||||
} \
|
||||
else if (opcode == WASM_OP_ATOMIC_RMW_I64_##OP_NAME##16_U) { \
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); \
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(); \
|
||||
\
|
||||
os_mutex_lock(&memory->mem_lock); \
|
||||
os_mutex_lock(&module->e->mem_lock); \
|
||||
readv = (uint64)LOAD_U16(maddr); \
|
||||
STORE_U16(maddr, (uint16)(readv op sval)); \
|
||||
os_mutex_unlock(&memory->mem_lock); \
|
||||
os_mutex_unlock(&module->e->mem_lock); \
|
||||
} \
|
||||
else if (opcode == WASM_OP_ATOMIC_RMW_I64_##OP_NAME##32_U) { \
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); \
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(); \
|
||||
\
|
||||
os_mutex_lock(&memory->mem_lock); \
|
||||
os_mutex_lock(&module->e->mem_lock); \
|
||||
readv = (uint64)LOAD_U32(maddr); \
|
||||
STORE_U32(maddr, (uint32)(readv op sval)); \
|
||||
os_mutex_unlock(&memory->mem_lock); \
|
||||
os_mutex_unlock(&module->e->mem_lock); \
|
||||
} \
|
||||
else { \
|
||||
uint64 op_result; \
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr); \
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(); \
|
||||
\
|
||||
os_mutex_lock(&memory->mem_lock); \
|
||||
os_mutex_lock(&module->e->mem_lock); \
|
||||
readv = (uint64)LOAD_I64(maddr); \
|
||||
op_result = readv op sval; \
|
||||
STORE_I64(maddr, op_result); \
|
||||
os_mutex_unlock(&memory->mem_lock); \
|
||||
os_mutex_unlock(&module->e->mem_lock); \
|
||||
} \
|
||||
PUSH_I64(readv); \
|
||||
break; \
|
||||
|
@ -850,7 +850,7 @@ wasm_interp_call_func_native(WASMModuleInstance *module_inst,
|
|||
|
||||
wasm_exec_env_set_cur_frame(exec_env, frame);
|
||||
|
||||
cur_func_index = (uint32)(cur_func - module_inst->functions);
|
||||
cur_func_index = (uint32)(cur_func - module_inst->e->functions);
|
||||
bh_assert(cur_func_index < module_inst->module->import_function_count);
|
||||
native_func_pointer = module_inst->import_func_ptrs[cur_func_index];
|
||||
|
||||
|
@ -904,12 +904,12 @@ wasm_interp_call_func_native(WASMModuleInstance *module_inst,
|
|||
|
||||
#if WASM_ENABLE_FAST_JIT != 0
|
||||
bool
|
||||
jit_invoke_native(WASMExecEnv *exec_env, uint32 func_idx,
|
||||
WASMInterpFrame *prev_frame)
|
||||
fast_jit_invoke_native(WASMExecEnv *exec_env, uint32 func_idx,
|
||||
WASMInterpFrame *prev_frame)
|
||||
{
|
||||
WASMModuleInstance *module_inst =
|
||||
(WASMModuleInstance *)exec_env->module_inst;
|
||||
WASMFunctionInstance *cur_func = module_inst->functions + func_idx;
|
||||
WASMFunctionInstance *cur_func = module_inst->e->functions + func_idx;
|
||||
|
||||
wasm_interp_call_func_native(module_inst, exec_env, cur_func, prev_frame);
|
||||
return wasm_get_exception(module_inst) ? false : true;
|
||||
|
@ -1081,7 +1081,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
WASMFunctionInstance *cur_func,
|
||||
WASMInterpFrame *prev_frame)
|
||||
{
|
||||
WASMMemoryInstance *memory = module->default_memory;
|
||||
WASMMemoryInstance *memory = wasm_get_default_memory(module);
|
||||
uint8 *global_data = module->global_data;
|
||||
#if !defined(OS_ENABLE_HW_BOUND_CHECK) \
|
||||
|| WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0 \
|
||||
|
@ -1091,7 +1091,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
memory ? num_bytes_per_page * memory->cur_page_count : 0;
|
||||
#endif
|
||||
WASMType **wasm_types = module->module->types;
|
||||
WASMGlobalInstance *globals = module->globals, *global;
|
||||
WASMGlobalInstance *globals = module->e->globals, *global;
|
||||
uint8 opcode_IMPDEP = WASM_OP_IMPDEP;
|
||||
WASMInterpFrame *frame = NULL;
|
||||
/* Points to this special opcode so as to jump to the
|
||||
|
@ -1355,13 +1355,13 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
#endif
|
||||
read_leb_uint32(frame_ip, frame_ip_end, fidx);
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
if (fidx >= module->function_count) {
|
||||
if (fidx >= module->e->function_count) {
|
||||
wasm_set_exception(module, "unknown function");
|
||||
goto got_exception;
|
||||
}
|
||||
#endif
|
||||
|
||||
cur_func = module->functions + fidx;
|
||||
cur_func = module->e->functions + fidx;
|
||||
goto call_func_from_interp;
|
||||
}
|
||||
|
||||
|
@ -1373,12 +1373,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
#endif
|
||||
read_leb_uint32(frame_ip, frame_ip_end, fidx);
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
if (fidx >= module->function_count) {
|
||||
if (fidx >= module->e->function_count) {
|
||||
wasm_set_exception(module, "unknown function");
|
||||
goto got_exception;
|
||||
}
|
||||
#endif
|
||||
cur_func = module->functions + fidx;
|
||||
cur_func = module->e->functions + fidx;
|
||||
|
||||
goto call_func_from_return_call;
|
||||
}
|
||||
|
@ -1420,8 +1420,8 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
goto got_exception;
|
||||
}
|
||||
|
||||
fidx = ((uint32 *)tbl_inst->base_addr)[val];
|
||||
if (fidx == (uint32)-1) {
|
||||
fidx = tbl_inst->elems[val];
|
||||
if (fidx == NULL_REF) {
|
||||
wasm_set_exception(module, "uninitialized element");
|
||||
goto got_exception;
|
||||
}
|
||||
|
@ -1431,13 +1431,13 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
* another module. In that case, we don't validate
|
||||
* the elem value while loading
|
||||
*/
|
||||
if (fidx >= module->function_count) {
|
||||
if (fidx >= module->e->function_count) {
|
||||
wasm_set_exception(module, "unknown function");
|
||||
goto got_exception;
|
||||
}
|
||||
|
||||
/* always call module own functions */
|
||||
cur_func = module->functions + fidx;
|
||||
cur_func = module->e->functions + fidx;
|
||||
|
||||
if (cur_func->is_import_func)
|
||||
cur_func_type = cur_func->u.func_import->func_type;
|
||||
|
@ -1531,7 +1531,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
goto got_exception;
|
||||
}
|
||||
|
||||
PUSH_I32(((uint32 *)tbl_inst->base_addr)[elem_idx]);
|
||||
PUSH_I32(tbl_inst->elems[elem_idx]);
|
||||
HANDLE_OP_END();
|
||||
}
|
||||
|
||||
|
@ -1552,7 +1552,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
goto got_exception;
|
||||
}
|
||||
|
||||
((uint32 *)(tbl_inst->base_addr))[elem_idx] = elem_val;
|
||||
tbl_inst->elems[elem_idx] = elem_val;
|
||||
HANDLE_OP_END();
|
||||
}
|
||||
|
||||
|
@ -1700,7 +1700,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
HANDLE_OP(WASM_OP_GET_GLOBAL)
|
||||
{
|
||||
read_leb_uint32(frame_ip, frame_ip_end, global_idx);
|
||||
bh_assert(global_idx < module->global_count);
|
||||
bh_assert(global_idx < module->e->global_count);
|
||||
global = globals + global_idx;
|
||||
global_addr = get_global_addr(global_data, global);
|
||||
PUSH_I32(*(uint32 *)global_addr);
|
||||
|
@ -1710,7 +1710,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
HANDLE_OP(WASM_OP_GET_GLOBAL_64)
|
||||
{
|
||||
read_leb_uint32(frame_ip, frame_ip_end, global_idx);
|
||||
bh_assert(global_idx < module->global_count);
|
||||
bh_assert(global_idx < module->e->global_count);
|
||||
global = globals + global_idx;
|
||||
global_addr = get_global_addr(global_data, global);
|
||||
PUSH_I64(GET_I64_FROM_ADDR((uint32 *)global_addr));
|
||||
|
@ -1720,7 +1720,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
HANDLE_OP(WASM_OP_SET_GLOBAL)
|
||||
{
|
||||
read_leb_uint32(frame_ip, frame_ip_end, global_idx);
|
||||
bh_assert(global_idx < module->global_count);
|
||||
bh_assert(global_idx < module->e->global_count);
|
||||
global = globals + global_idx;
|
||||
global_addr = get_global_addr(global_data, global);
|
||||
*(int32 *)global_addr = POP_I32();
|
||||
|
@ -1732,7 +1732,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
uint32 aux_stack_top;
|
||||
|
||||
read_leb_uint32(frame_ip, frame_ip_end, global_idx);
|
||||
bh_assert(global_idx < module->global_count);
|
||||
bh_assert(global_idx < module->e->global_count);
|
||||
global = globals + global_idx;
|
||||
global_addr = get_global_addr(global_data, global);
|
||||
aux_stack_top = *(uint32 *)(frame_sp - 1);
|
||||
|
@ -1751,8 +1751,8 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
if (module->module->aux_stack_top_global_index != (uint32)-1) {
|
||||
uint32 aux_stack_used = module->module->aux_stack_bottom
|
||||
- *(uint32 *)global_addr;
|
||||
if (aux_stack_used > module->max_aux_stack_used)
|
||||
module->max_aux_stack_used = aux_stack_used;
|
||||
if (aux_stack_used > module->e->max_aux_stack_used)
|
||||
module->e->max_aux_stack_used = aux_stack_used;
|
||||
}
|
||||
#endif
|
||||
HANDLE_OP_END();
|
||||
|
@ -1761,7 +1761,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
HANDLE_OP(WASM_OP_SET_GLOBAL_64)
|
||||
{
|
||||
read_leb_uint32(frame_ip, frame_ip_end, global_idx);
|
||||
bh_assert(global_idx < module->global_count);
|
||||
bh_assert(global_idx < module->e->global_count);
|
||||
global = globals + global_idx;
|
||||
global_addr = get_global_addr(global_data, global);
|
||||
PUT_I64_TO_ADDR((uint32 *)global_addr, POP_I64());
|
||||
|
@ -2039,8 +2039,8 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
else {
|
||||
/* success, return previous page count */
|
||||
PUSH_I32(prev_page_count);
|
||||
/* update memory instance ptr and memory size */
|
||||
memory = module->default_memory;
|
||||
/* update memory size, no need to update memory ptr as
|
||||
it isn't changed in wasm_enlarge_memory */
|
||||
#if !defined(OS_ENABLE_HW_BOUND_CHECK) \
|
||||
|| WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0 \
|
||||
|| WASM_ENABLE_BULK_MEMORY != 0
|
||||
|
@ -3195,8 +3195,8 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
}
|
||||
|
||||
bh_memcpy_s(
|
||||
(uint8 *)(tbl_inst)
|
||||
+ offsetof(WASMTableInstance, base_addr)
|
||||
(uint8 *)tbl_inst
|
||||
+ offsetof(WASMTableInstance, elems)
|
||||
+ d * sizeof(uint32),
|
||||
(uint32)((tbl_inst->cur_size - d) * sizeof(uint32)),
|
||||
module->module->table_segments[elem_idx]
|
||||
|
@ -3246,16 +3246,15 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
/* if s >= d, copy from front to back */
|
||||
/* if s < d, copy from back to front */
|
||||
/* merge all together */
|
||||
bh_memmove_s(
|
||||
(uint8 *)(dst_tbl_inst)
|
||||
+ offsetof(WASMTableInstance, base_addr)
|
||||
+ d * sizeof(uint32),
|
||||
(uint32)((dst_tbl_inst->cur_size - d)
|
||||
* sizeof(uint32)),
|
||||
(uint8 *)(src_tbl_inst)
|
||||
+ offsetof(WASMTableInstance, base_addr)
|
||||
+ s * sizeof(uint32),
|
||||
(uint32)(n * sizeof(uint32)));
|
||||
bh_memmove_s((uint8 *)dst_tbl_inst
|
||||
+ offsetof(WASMTableInstance, elems)
|
||||
+ d * sizeof(uint32),
|
||||
(uint32)((dst_tbl_inst->cur_size - d)
|
||||
* sizeof(uint32)),
|
||||
(uint8 *)src_tbl_inst
|
||||
+ offsetof(WASMTableInstance, elems)
|
||||
+ s * sizeof(uint32),
|
||||
(uint32)(n * sizeof(uint32)));
|
||||
break;
|
||||
}
|
||||
case WASM_OP_TABLE_GROW:
|
||||
|
@ -3319,7 +3318,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
}
|
||||
|
||||
for (; n != 0; i++, n--) {
|
||||
((uint32 *)(tbl_inst->base_addr))[i] = fill_val;
|
||||
tbl_inst->elems[i] = fill_val;
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -3420,23 +3419,23 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
if (opcode == WASM_OP_ATOMIC_I32_LOAD8_U) {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS();
|
||||
os_mutex_lock(&memory->mem_lock);
|
||||
os_mutex_lock(&module->e->mem_lock);
|
||||
readv = (uint32)(*(uint8 *)maddr);
|
||||
os_mutex_unlock(&memory->mem_lock);
|
||||
os_mutex_unlock(&module->e->mem_lock);
|
||||
}
|
||||
else if (opcode == WASM_OP_ATOMIC_I32_LOAD16_U) {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS();
|
||||
os_mutex_lock(&memory->mem_lock);
|
||||
os_mutex_lock(&module->e->mem_lock);
|
||||
readv = (uint32)LOAD_U16(maddr);
|
||||
os_mutex_unlock(&memory->mem_lock);
|
||||
os_mutex_unlock(&module->e->mem_lock);
|
||||
}
|
||||
else {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS();
|
||||
os_mutex_lock(&memory->mem_lock);
|
||||
os_mutex_lock(&module->e->mem_lock);
|
||||
readv = LOAD_I32(maddr);
|
||||
os_mutex_unlock(&memory->mem_lock);
|
||||
os_mutex_unlock(&module->e->mem_lock);
|
||||
}
|
||||
|
||||
PUSH_I32(readv);
|
||||
|
@ -3455,30 +3454,30 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
if (opcode == WASM_OP_ATOMIC_I64_LOAD8_U) {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS();
|
||||
os_mutex_lock(&memory->mem_lock);
|
||||
os_mutex_lock(&module->e->mem_lock);
|
||||
readv = (uint64)(*(uint8 *)maddr);
|
||||
os_mutex_unlock(&memory->mem_lock);
|
||||
os_mutex_unlock(&module->e->mem_lock);
|
||||
}
|
||||
else if (opcode == WASM_OP_ATOMIC_I64_LOAD16_U) {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS();
|
||||
os_mutex_lock(&memory->mem_lock);
|
||||
os_mutex_lock(&module->e->mem_lock);
|
||||
readv = (uint64)LOAD_U16(maddr);
|
||||
os_mutex_unlock(&memory->mem_lock);
|
||||
os_mutex_unlock(&module->e->mem_lock);
|
||||
}
|
||||
else if (opcode == WASM_OP_ATOMIC_I64_LOAD32_U) {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS();
|
||||
os_mutex_lock(&memory->mem_lock);
|
||||
os_mutex_lock(&module->e->mem_lock);
|
||||
readv = (uint64)LOAD_U32(maddr);
|
||||
os_mutex_unlock(&memory->mem_lock);
|
||||
os_mutex_unlock(&module->e->mem_lock);
|
||||
}
|
||||
else {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS();
|
||||
os_mutex_lock(&memory->mem_lock);
|
||||
os_mutex_lock(&module->e->mem_lock);
|
||||
readv = LOAD_I64(maddr);
|
||||
os_mutex_unlock(&memory->mem_lock);
|
||||
os_mutex_unlock(&module->e->mem_lock);
|
||||
}
|
||||
|
||||
PUSH_I64(readv);
|
||||
|
@ -3497,23 +3496,23 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
if (opcode == WASM_OP_ATOMIC_I32_STORE8) {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS();
|
||||
os_mutex_lock(&memory->mem_lock);
|
||||
os_mutex_lock(&module->e->mem_lock);
|
||||
*(uint8 *)maddr = (uint8)sval;
|
||||
os_mutex_unlock(&memory->mem_lock);
|
||||
os_mutex_unlock(&module->e->mem_lock);
|
||||
}
|
||||
else if (opcode == WASM_OP_ATOMIC_I32_STORE16) {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS();
|
||||
os_mutex_lock(&memory->mem_lock);
|
||||
os_mutex_lock(&module->e->mem_lock);
|
||||
STORE_U16(maddr, (uint16)sval);
|
||||
os_mutex_unlock(&memory->mem_lock);
|
||||
os_mutex_unlock(&module->e->mem_lock);
|
||||
}
|
||||
else {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS();
|
||||
os_mutex_lock(&memory->mem_lock);
|
||||
os_mutex_lock(&module->e->mem_lock);
|
||||
STORE_U32(maddr, frame_sp[1]);
|
||||
os_mutex_unlock(&memory->mem_lock);
|
||||
os_mutex_unlock(&module->e->mem_lock);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -3531,31 +3530,31 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
if (opcode == WASM_OP_ATOMIC_I64_STORE8) {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS();
|
||||
os_mutex_lock(&memory->mem_lock);
|
||||
os_mutex_lock(&module->e->mem_lock);
|
||||
*(uint8 *)maddr = (uint8)sval;
|
||||
os_mutex_unlock(&memory->mem_lock);
|
||||
os_mutex_unlock(&module->e->mem_lock);
|
||||
}
|
||||
else if (opcode == WASM_OP_ATOMIC_I64_STORE16) {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS();
|
||||
os_mutex_lock(&memory->mem_lock);
|
||||
os_mutex_lock(&module->e->mem_lock);
|
||||
STORE_U16(maddr, (uint16)sval);
|
||||
os_mutex_unlock(&memory->mem_lock);
|
||||
os_mutex_unlock(&module->e->mem_lock);
|
||||
}
|
||||
else if (opcode == WASM_OP_ATOMIC_I64_STORE32) {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS();
|
||||
os_mutex_lock(&memory->mem_lock);
|
||||
os_mutex_lock(&module->e->mem_lock);
|
||||
STORE_U32(maddr, (uint32)sval);
|
||||
os_mutex_unlock(&memory->mem_lock);
|
||||
os_mutex_unlock(&module->e->mem_lock);
|
||||
}
|
||||
else {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS();
|
||||
os_mutex_lock(&memory->mem_lock);
|
||||
os_mutex_lock(&module->e->mem_lock);
|
||||
PUT_I64_TO_ADDR((uint32 *)maddr,
|
||||
GET_I64_FROM_ADDR(frame_sp + 1));
|
||||
os_mutex_unlock(&memory->mem_lock);
|
||||
os_mutex_unlock(&module->e->mem_lock);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -3575,32 +3574,32 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
CHECK_ATOMIC_MEMORY_ACCESS();
|
||||
|
||||
expect = (uint8)expect;
|
||||
os_mutex_lock(&memory->mem_lock);
|
||||
os_mutex_lock(&module->e->mem_lock);
|
||||
readv = (uint32)(*(uint8 *)maddr);
|
||||
if (readv == expect)
|
||||
*(uint8 *)maddr = (uint8)(sval);
|
||||
os_mutex_unlock(&memory->mem_lock);
|
||||
os_mutex_unlock(&module->e->mem_lock);
|
||||
}
|
||||
else if (opcode == WASM_OP_ATOMIC_RMW_I32_CMPXCHG16_U) {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS();
|
||||
|
||||
expect = (uint16)expect;
|
||||
os_mutex_lock(&memory->mem_lock);
|
||||
os_mutex_lock(&module->e->mem_lock);
|
||||
readv = (uint32)LOAD_U16(maddr);
|
||||
if (readv == expect)
|
||||
STORE_U16(maddr, (uint16)(sval));
|
||||
os_mutex_unlock(&memory->mem_lock);
|
||||
os_mutex_unlock(&module->e->mem_lock);
|
||||
}
|
||||
else {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS();
|
||||
|
||||
os_mutex_lock(&memory->mem_lock);
|
||||
os_mutex_lock(&module->e->mem_lock);
|
||||
readv = LOAD_I32(maddr);
|
||||
if (readv == expect)
|
||||
STORE_U32(maddr, sval);
|
||||
os_mutex_unlock(&memory->mem_lock);
|
||||
os_mutex_unlock(&module->e->mem_lock);
|
||||
}
|
||||
PUSH_I32(readv);
|
||||
break;
|
||||
|
@ -3621,44 +3620,44 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
CHECK_ATOMIC_MEMORY_ACCESS();
|
||||
|
||||
expect = (uint8)expect;
|
||||
os_mutex_lock(&memory->mem_lock);
|
||||
os_mutex_lock(&module->e->mem_lock);
|
||||
readv = (uint64)(*(uint8 *)maddr);
|
||||
if (readv == expect)
|
||||
*(uint8 *)maddr = (uint8)(sval);
|
||||
os_mutex_unlock(&memory->mem_lock);
|
||||
os_mutex_unlock(&module->e->mem_lock);
|
||||
}
|
||||
else if (opcode == WASM_OP_ATOMIC_RMW_I64_CMPXCHG16_U) {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS();
|
||||
|
||||
expect = (uint16)expect;
|
||||
os_mutex_lock(&memory->mem_lock);
|
||||
os_mutex_lock(&module->e->mem_lock);
|
||||
readv = (uint64)LOAD_U16(maddr);
|
||||
if (readv == expect)
|
||||
STORE_U16(maddr, (uint16)(sval));
|
||||
os_mutex_unlock(&memory->mem_lock);
|
||||
os_mutex_unlock(&module->e->mem_lock);
|
||||
}
|
||||
else if (opcode == WASM_OP_ATOMIC_RMW_I64_CMPXCHG32_U) {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS();
|
||||
|
||||
expect = (uint32)expect;
|
||||
os_mutex_lock(&memory->mem_lock);
|
||||
os_mutex_lock(&module->e->mem_lock);
|
||||
readv = (uint64)LOAD_U32(maddr);
|
||||
if (readv == expect)
|
||||
STORE_U32(maddr, (uint32)(sval));
|
||||
os_mutex_unlock(&memory->mem_lock);
|
||||
os_mutex_unlock(&module->e->mem_lock);
|
||||
}
|
||||
else {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS();
|
||||
|
||||
os_mutex_lock(&memory->mem_lock);
|
||||
os_mutex_lock(&module->e->mem_lock);
|
||||
readv = (uint64)LOAD_I64(maddr);
|
||||
if (readv == expect) {
|
||||
STORE_I64(maddr, sval);
|
||||
}
|
||||
os_mutex_unlock(&memory->mem_lock);
|
||||
os_mutex_unlock(&module->e->mem_lock);
|
||||
}
|
||||
PUSH_I64(readv);
|
||||
break;
|
||||
|
@ -3794,8 +3793,8 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
cur_func = frame->function;
|
||||
UPDATE_ALL_FROM_FRAME();
|
||||
|
||||
/* update memory instance ptr and memory size */
|
||||
memory = module->default_memory;
|
||||
/* update memory size, no need to update memory ptr as
|
||||
it isn't changed in wasm_enlarge_memory */
|
||||
#if !defined(OS_ENABLE_HW_BOUND_CHECK) \
|
||||
|| WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0 \
|
||||
|| WASM_ENABLE_BULK_MEMORY != 0
|
||||
|
@ -3905,6 +3904,191 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
#endif
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_FAST_JIT != 0
|
||||
static void
|
||||
fast_jit_call_func_bytecode(WASMExecEnv *exec_env,
|
||||
WASMFunctionInstance *function,
|
||||
WASMInterpFrame *frame)
|
||||
{
|
||||
JitGlobals *jit_globals = jit_compiler_get_jit_globals();
|
||||
JitInterpSwitchInfo info;
|
||||
WASMType *func_type = function->u.func->func_type;
|
||||
uint8 type = func_type->result_count
|
||||
? func_type->types[func_type->param_count]
|
||||
: VALUE_TYPE_VOID;
|
||||
|
||||
#if WASM_ENABLE_REF_TYPES != 0
|
||||
if (type == VALUE_TYPE_EXTERNREF || type == VALUE_TYPE_FUNCREF)
|
||||
type = VALUE_TYPE_I32;
|
||||
#endif
|
||||
|
||||
info.out.ret.last_return_type = type;
|
||||
info.frame = frame;
|
||||
frame->jitted_return_addr =
|
||||
(uint8 *)jit_globals->return_to_interp_from_jitted;
|
||||
jit_interp_switch_to_jitted(exec_env, &info,
|
||||
function->u.func->fast_jit_jitted_code);
|
||||
if (func_type->result_count) {
|
||||
switch (type) {
|
||||
case VALUE_TYPE_I32:
|
||||
*(frame->sp - function->ret_cell_num) = info.out.ret.ival[0];
|
||||
break;
|
||||
case VALUE_TYPE_I64:
|
||||
*(frame->sp - function->ret_cell_num) = info.out.ret.ival[0];
|
||||
*(frame->sp - function->ret_cell_num + 1) =
|
||||
info.out.ret.ival[1];
|
||||
break;
|
||||
case VALUE_TYPE_F32:
|
||||
*(frame->sp - function->ret_cell_num) = info.out.ret.fval[0];
|
||||
break;
|
||||
case VALUE_TYPE_F64:
|
||||
*(frame->sp - function->ret_cell_num) = info.out.ret.fval[0];
|
||||
*(frame->sp - function->ret_cell_num + 1) =
|
||||
info.out.ret.fval[1];
|
||||
break;
|
||||
default:
|
||||
bh_assert(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_JIT != 0
|
||||
static bool
|
||||
clear_wasi_proc_exit_exception(WASMModuleInstance *module_inst)
|
||||
{
|
||||
#if WASM_ENABLE_LIBC_WASI != 0
|
||||
const char *exception = wasm_get_exception(module_inst);
|
||||
if (exception && !strcmp(exception, "Exception: wasi proc exit")) {
|
||||
/* The "wasi proc exit" exception is thrown by native lib to
|
||||
let wasm app exit, which is a normal behavior, we clear
|
||||
the exception here. */
|
||||
wasm_set_exception(module_inst, NULL);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool
|
||||
llvm_jit_call_func_bytecode(WASMModuleInstance *module_inst,
|
||||
WASMExecEnv *exec_env,
|
||||
WASMFunctionInstance *function, uint32 argc,
|
||||
uint32 argv[])
|
||||
{
|
||||
WASMType *func_type = function->u.func->func_type;
|
||||
uint32 result_count = func_type->result_count;
|
||||
uint32 ext_ret_count = result_count > 1 ? result_count - 1 : 0;
|
||||
bool ret;
|
||||
|
||||
#if (WASM_ENABLE_DUMP_CALL_STACK != 0) || (WASM_ENABLE_PERF_PROFILING != 0)
|
||||
if (!llvm_jit_alloc_frame(exec_env, function - module_inst->e->functions)) {
|
||||
wasm_set_exception(module_inst, "wasm operand stack overflow");
|
||||
}
|
||||
#endif
|
||||
|
||||
if (ext_ret_count > 0) {
|
||||
uint32 cell_num = 0, i;
|
||||
uint8 *ext_ret_types = func_type->types + func_type->param_count + 1;
|
||||
uint32 argv1_buf[32], *argv1 = argv1_buf, *ext_rets = NULL;
|
||||
uint32 *argv_ret = argv;
|
||||
uint32 ext_ret_cell = wasm_get_cell_num(ext_ret_types, ext_ret_count);
|
||||
uint64 size;
|
||||
|
||||
/* Allocate memory all arguments */
|
||||
size =
|
||||
sizeof(uint32) * (uint64)argc /* original arguments */
|
||||
+ sizeof(void *)
|
||||
* (uint64)ext_ret_count /* extra result values' addr */
|
||||
+ sizeof(uint32) * (uint64)ext_ret_cell; /* extra result values */
|
||||
if (size > sizeof(argv1_buf)) {
|
||||
if (size > UINT32_MAX
|
||||
|| !(argv1 = wasm_runtime_malloc((uint32)size))) {
|
||||
wasm_set_exception(module_inst, "allocate memory failed");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Copy original arguments */
|
||||
bh_memcpy_s(argv1, (uint32)size, argv, sizeof(uint32) * argc);
|
||||
|
||||
/* Get the extra result value's address */
|
||||
ext_rets =
|
||||
argv1 + argc + sizeof(void *) / sizeof(uint32) * ext_ret_count;
|
||||
|
||||
/* Append each extra result value's address to original arguments */
|
||||
for (i = 0; i < ext_ret_count; i++) {
|
||||
*(uintptr_t *)(argv1 + argc + sizeof(void *) / sizeof(uint32) * i) =
|
||||
(uintptr_t)(ext_rets + cell_num);
|
||||
cell_num += wasm_value_type_cell_num(ext_ret_types[i]);
|
||||
}
|
||||
|
||||
ret = wasm_runtime_invoke_native(
|
||||
exec_env, function->u.func->llvm_jit_func_ptr, func_type, NULL,
|
||||
NULL, argv1, argc, argv);
|
||||
|
||||
if (!ret || wasm_get_exception(module_inst)) {
|
||||
if (clear_wasi_proc_exit_exception(module_inst))
|
||||
ret = true;
|
||||
else
|
||||
ret = false;
|
||||
}
|
||||
|
||||
if (!ret) {
|
||||
if (argv1 != argv1_buf)
|
||||
wasm_runtime_free(argv1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Get extra result values */
|
||||
switch (func_type->types[func_type->param_count]) {
|
||||
case VALUE_TYPE_I32:
|
||||
case VALUE_TYPE_F32:
|
||||
#if WASM_ENABLE_REF_TYPES != 0
|
||||
case VALUE_TYPE_FUNCREF:
|
||||
case VALUE_TYPE_EXTERNREF:
|
||||
#endif
|
||||
argv_ret++;
|
||||
break;
|
||||
case VALUE_TYPE_I64:
|
||||
case VALUE_TYPE_F64:
|
||||
argv_ret += 2;
|
||||
break;
|
||||
#if WASM_ENABLE_SIMD != 0
|
||||
case VALUE_TYPE_V128:
|
||||
argv_ret += 4;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
bh_assert(0);
|
||||
break;
|
||||
}
|
||||
|
||||
ext_rets =
|
||||
argv1 + argc + sizeof(void *) / sizeof(uint32) * ext_ret_count;
|
||||
bh_memcpy_s(argv_ret, sizeof(uint32) * cell_num, ext_rets,
|
||||
sizeof(uint32) * cell_num);
|
||||
|
||||
if (argv1 != argv1_buf)
|
||||
wasm_runtime_free(argv1);
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
ret = wasm_runtime_invoke_native(
|
||||
exec_env, function->u.func->llvm_jit_func_ptr, func_type, NULL,
|
||||
NULL, argv, argc, argv);
|
||||
|
||||
if (clear_wasi_proc_exit_exception(module_inst))
|
||||
ret = true;
|
||||
|
||||
return ret && !wasm_get_exception(module_inst) ? true : false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
wasm_interp_call_wasm(WASMModuleInstance *module_inst, WASMExecEnv *exec_env,
|
||||
WASMFunctionInstance *function, uint32 argc,
|
||||
|
@ -3912,14 +4096,14 @@ wasm_interp_call_wasm(WASMModuleInstance *module_inst, WASMExecEnv *exec_env,
|
|||
{
|
||||
WASMRuntimeFrame *prev_frame = wasm_exec_env_get_cur_frame(exec_env);
|
||||
WASMInterpFrame *frame, *outs_area;
|
||||
|
||||
/* Allocate sufficient cells for all kinds of return values. */
|
||||
unsigned all_cell_num =
|
||||
function->ret_cell_num > 2 ? function->ret_cell_num : 2,
|
||||
i;
|
||||
function->ret_cell_num > 2 ? function->ret_cell_num : 2;
|
||||
/* This frame won't be used by JITed code, so only allocate interp
|
||||
frame here. */
|
||||
unsigned frame_size = wasm_interp_interp_frame_size(all_cell_num);
|
||||
unsigned i;
|
||||
bool copy_argv_from_frame = true;
|
||||
|
||||
if (argc < function->param_cell_num) {
|
||||
char buf[128];
|
||||
|
@ -3969,62 +4153,26 @@ wasm_interp_call_wasm(WASMModuleInstance *module_inst, WASMExecEnv *exec_env,
|
|||
}
|
||||
}
|
||||
else {
|
||||
#if WASM_ENABLE_FAST_JIT == 0
|
||||
wasm_interp_call_func_bytecode(module_inst, exec_env, function, frame);
|
||||
#if WASM_ENABLE_JIT != 0
|
||||
llvm_jit_call_func_bytecode(module_inst, exec_env, function, argc,
|
||||
argv);
|
||||
/* For llvm jit, the results have been stored in argv,
|
||||
no need to copy them from stack frame again */
|
||||
copy_argv_from_frame = false;
|
||||
#elif WASM_ENABLE_FAST_JIT != 0
|
||||
fast_jit_call_func_bytecode(exec_env, function, frame);
|
||||
#else
|
||||
JitGlobals *jit_globals = jit_compiler_get_jit_globals();
|
||||
JitInterpSwitchInfo info;
|
||||
WASMType *func_type = function->u.func->func_type;
|
||||
uint8 type = func_type->result_count
|
||||
? func_type->types[func_type->param_count]
|
||||
: VALUE_TYPE_VOID;
|
||||
|
||||
#if WASM_ENABLE_REF_TYPES != 0
|
||||
if (type == VALUE_TYPE_EXTERNREF || type == VALUE_TYPE_FUNCREF)
|
||||
type = VALUE_TYPE_I32;
|
||||
wasm_interp_call_func_bytecode(module_inst, exec_env, function, frame);
|
||||
#endif
|
||||
|
||||
info.out.ret.last_return_type = type;
|
||||
info.frame = frame;
|
||||
frame->jitted_return_addr =
|
||||
(uint8 *)jit_globals->return_to_interp_from_jitted;
|
||||
jit_interp_switch_to_jitted(exec_env, &info,
|
||||
function->u.func->fast_jit_jitted_code);
|
||||
if (func_type->result_count) {
|
||||
switch (type) {
|
||||
case VALUE_TYPE_I32:
|
||||
*(frame->sp - function->ret_cell_num) =
|
||||
info.out.ret.ival[0];
|
||||
break;
|
||||
case VALUE_TYPE_I64:
|
||||
*(frame->sp - function->ret_cell_num) =
|
||||
info.out.ret.ival[0];
|
||||
*(frame->sp - function->ret_cell_num + 1) =
|
||||
info.out.ret.ival[1];
|
||||
break;
|
||||
case VALUE_TYPE_F32:
|
||||
*(frame->sp - function->ret_cell_num) =
|
||||
info.out.ret.fval[0];
|
||||
break;
|
||||
case VALUE_TYPE_F64:
|
||||
*(frame->sp - function->ret_cell_num) =
|
||||
info.out.ret.fval[0];
|
||||
*(frame->sp - function->ret_cell_num + 1) =
|
||||
info.out.ret.fval[1];
|
||||
break;
|
||||
default:
|
||||
bh_assert(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
(void)wasm_interp_call_func_bytecode;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Output the return value to the caller */
|
||||
if (!wasm_get_exception(module_inst)) {
|
||||
for (i = 0; i < function->ret_cell_num; i++) {
|
||||
argv[i] = *(frame->sp + i - function->ret_cell_num);
|
||||
if (copy_argv_from_frame) {
|
||||
for (i = 0; i < function->ret_cell_num; i++) {
|
||||
argv[i] = *(frame->sp + i - function->ret_cell_num);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -443,28 +443,28 @@ LOAD_PTR(void *addr)
|
|||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); \
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(1); \
|
||||
\
|
||||
os_mutex_lock(&memory->mem_lock); \
|
||||
os_mutex_lock(&module->e->mem_lock); \
|
||||
readv = (uint32)(*(uint8 *)maddr); \
|
||||
*(uint8 *)maddr = (uint8)(readv op sval); \
|
||||
os_mutex_unlock(&memory->mem_lock); \
|
||||
os_mutex_unlock(&module->e->mem_lock); \
|
||||
} \
|
||||
else if (opcode == WASM_OP_ATOMIC_RMW_I32_##OP_NAME##16_U) { \
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); \
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(2); \
|
||||
\
|
||||
os_mutex_lock(&memory->mem_lock); \
|
||||
os_mutex_lock(&module->e->mem_lock); \
|
||||
readv = (uint32)LOAD_U16(maddr); \
|
||||
STORE_U16(maddr, (uint16)(readv op sval)); \
|
||||
os_mutex_unlock(&memory->mem_lock); \
|
||||
os_mutex_unlock(&module->e->mem_lock); \
|
||||
} \
|
||||
else { \
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); \
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(4); \
|
||||
\
|
||||
os_mutex_lock(&memory->mem_lock); \
|
||||
os_mutex_lock(&module->e->mem_lock); \
|
||||
readv = LOAD_I32(maddr); \
|
||||
STORE_U32(maddr, readv op sval); \
|
||||
os_mutex_unlock(&memory->mem_lock); \
|
||||
os_mutex_unlock(&module->e->mem_lock); \
|
||||
} \
|
||||
PUSH_I32(readv); \
|
||||
break; \
|
||||
|
@ -483,39 +483,39 @@ LOAD_PTR(void *addr)
|
|||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr); \
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(1); \
|
||||
\
|
||||
os_mutex_lock(&memory->mem_lock); \
|
||||
os_mutex_lock(&module->e->mem_lock); \
|
||||
readv = (uint64)(*(uint8 *)maddr); \
|
||||
*(uint8 *)maddr = (uint8)(readv op sval); \
|
||||
os_mutex_unlock(&memory->mem_lock); \
|
||||
os_mutex_unlock(&module->e->mem_lock); \
|
||||
} \
|
||||
else if (opcode == WASM_OP_ATOMIC_RMW_I64_##OP_NAME##16_U) { \
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr); \
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(2); \
|
||||
\
|
||||
os_mutex_lock(&memory->mem_lock); \
|
||||
os_mutex_lock(&module->e->mem_lock); \
|
||||
readv = (uint64)LOAD_U16(maddr); \
|
||||
STORE_U16(maddr, (uint16)(readv op sval)); \
|
||||
os_mutex_unlock(&memory->mem_lock); \
|
||||
os_mutex_unlock(&module->e->mem_lock); \
|
||||
} \
|
||||
else if (opcode == WASM_OP_ATOMIC_RMW_I64_##OP_NAME##32_U) { \
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr); \
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(4); \
|
||||
\
|
||||
os_mutex_lock(&memory->mem_lock); \
|
||||
os_mutex_lock(&module->e->mem_lock); \
|
||||
readv = (uint64)LOAD_U32(maddr); \
|
||||
STORE_U32(maddr, (uint32)(readv op sval)); \
|
||||
os_mutex_unlock(&memory->mem_lock); \
|
||||
os_mutex_unlock(&module->e->mem_lock); \
|
||||
} \
|
||||
else { \
|
||||
uint64 op_result; \
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr); \
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(8); \
|
||||
\
|
||||
os_mutex_lock(&memory->mem_lock); \
|
||||
os_mutex_lock(&module->e->mem_lock); \
|
||||
readv = (uint64)LOAD_I64(maddr); \
|
||||
op_result = readv op sval; \
|
||||
STORE_I64(maddr, op_result); \
|
||||
os_mutex_unlock(&memory->mem_lock); \
|
||||
os_mutex_unlock(&module->e->mem_lock); \
|
||||
} \
|
||||
PUSH_I64(readv); \
|
||||
break; \
|
||||
|
@ -913,7 +913,7 @@ wasm_interp_call_func_native(WASMModuleInstance *module_inst,
|
|||
|
||||
wasm_exec_env_set_cur_frame(exec_env, frame);
|
||||
|
||||
cur_func_index = (uint32)(cur_func - module_inst->functions);
|
||||
cur_func_index = (uint32)(cur_func - module_inst->e->functions);
|
||||
bh_assert(cur_func_index < module_inst->module->import_function_count);
|
||||
native_func_pointer = module_inst->import_func_ptrs[cur_func_index];
|
||||
|
||||
|
@ -1138,7 +1138,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
WASMFunctionInstance *cur_func,
|
||||
WASMInterpFrame *prev_frame)
|
||||
{
|
||||
WASMMemoryInstance *memory = module->default_memory;
|
||||
WASMMemoryInstance *memory = wasm_get_default_memory(module);
|
||||
#if !defined(OS_ENABLE_HW_BOUND_CHECK) \
|
||||
|| WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0 \
|
||||
|| WASM_ENABLE_BULK_MEMORY != 0
|
||||
|
@ -1147,7 +1147,8 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
memory ? num_bytes_per_page * memory->cur_page_count : 0;
|
||||
#endif
|
||||
uint8 *global_data = module->global_data;
|
||||
WASMGlobalInstance *globals = module->globals, *global;
|
||||
WASMGlobalInstance *globals = module->e ? module->e->globals : NULL;
|
||||
WASMGlobalInstance *global;
|
||||
uint8 opcode_IMPDEP = WASM_OP_IMPDEP;
|
||||
WASMInterpFrame *frame = NULL;
|
||||
/* Points to this special opcode so as to jump to the
|
||||
|
@ -1345,8 +1346,8 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
goto got_exception;
|
||||
}
|
||||
|
||||
fidx = ((uint32 *)tbl_inst->base_addr)[val];
|
||||
if (fidx == (uint32)-1) {
|
||||
fidx = tbl_inst->elems[val];
|
||||
if (fidx == NULL_REF) {
|
||||
wasm_set_exception(module, "uninitialized element");
|
||||
goto got_exception;
|
||||
}
|
||||
|
@ -1356,13 +1357,13 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
* another module. in that case, we don't validate
|
||||
* the elem value while loading
|
||||
*/
|
||||
if (fidx >= module->function_count) {
|
||||
if (fidx >= module->e->function_count) {
|
||||
wasm_set_exception(module, "unknown function");
|
||||
goto got_exception;
|
||||
}
|
||||
|
||||
/* always call module own functions */
|
||||
cur_func = module->functions + fidx;
|
||||
cur_func = module->e->functions + fidx;
|
||||
|
||||
if (cur_func->is_import_func)
|
||||
cur_func_type = cur_func->u.func_import->func_type;
|
||||
|
@ -1437,7 +1438,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
goto got_exception;
|
||||
}
|
||||
|
||||
PUSH_I32(((uint32 *)tbl_inst->base_addr)[elem_idx]);
|
||||
PUSH_I32(tbl_inst->elems[elem_idx]);
|
||||
HANDLE_OP_END();
|
||||
}
|
||||
|
||||
|
@ -1458,7 +1459,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
goto got_exception;
|
||||
}
|
||||
|
||||
((uint32 *)tbl_inst->base_addr)[elem_idx] = elem_val;
|
||||
tbl_inst->elems[elem_idx] = elem_val;
|
||||
HANDLE_OP_END();
|
||||
}
|
||||
|
||||
|
@ -1522,7 +1523,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
HANDLE_OP(WASM_OP_GET_GLOBAL)
|
||||
{
|
||||
global_idx = read_uint32(frame_ip);
|
||||
bh_assert(global_idx < module->global_count);
|
||||
bh_assert(global_idx < module->e->global_count);
|
||||
global = globals + global_idx;
|
||||
global_addr = get_global_addr(global_data, global);
|
||||
addr_ret = GET_OFFSET();
|
||||
|
@ -1533,7 +1534,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
HANDLE_OP(WASM_OP_GET_GLOBAL_64)
|
||||
{
|
||||
global_idx = read_uint32(frame_ip);
|
||||
bh_assert(global_idx < module->global_count);
|
||||
bh_assert(global_idx < module->e->global_count);
|
||||
global = globals + global_idx;
|
||||
global_addr = get_global_addr(global_data, global);
|
||||
addr_ret = GET_OFFSET();
|
||||
|
@ -1545,7 +1546,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
HANDLE_OP(WASM_OP_SET_GLOBAL)
|
||||
{
|
||||
global_idx = read_uint32(frame_ip);
|
||||
bh_assert(global_idx < module->global_count);
|
||||
bh_assert(global_idx < module->e->global_count);
|
||||
global = globals + global_idx;
|
||||
global_addr = get_global_addr(global_data, global);
|
||||
addr1 = GET_OFFSET();
|
||||
|
@ -1558,7 +1559,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
uint32 aux_stack_top;
|
||||
|
||||
global_idx = read_uint32(frame_ip);
|
||||
bh_assert(global_idx < module->global_count);
|
||||
bh_assert(global_idx < module->e->global_count);
|
||||
global = globals + global_idx;
|
||||
global_addr = get_global_addr(global_data, global);
|
||||
aux_stack_top = frame_lp[GET_OFFSET()];
|
||||
|
@ -1576,8 +1577,8 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
if (module->module->aux_stack_top_global_index != (uint32)-1) {
|
||||
uint32 aux_stack_used = module->module->aux_stack_bottom
|
||||
- *(uint32 *)global_addr;
|
||||
if (aux_stack_used > module->max_aux_stack_used)
|
||||
module->max_aux_stack_used = aux_stack_used;
|
||||
if (aux_stack_used > module->e->max_aux_stack_used)
|
||||
module->e->max_aux_stack_used = aux_stack_used;
|
||||
}
|
||||
#endif
|
||||
HANDLE_OP_END();
|
||||
|
@ -1586,7 +1587,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
HANDLE_OP(WASM_OP_SET_GLOBAL_64)
|
||||
{
|
||||
global_idx = read_uint32(frame_ip);
|
||||
bh_assert(global_idx < module->global_count);
|
||||
bh_assert(global_idx < module->e->global_count);
|
||||
global = globals + global_idx;
|
||||
global_addr = get_global_addr(global_data, global);
|
||||
addr1 = GET_OFFSET();
|
||||
|
@ -1860,8 +1861,8 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
else {
|
||||
/* success, return previous page count */
|
||||
frame_lp[addr_ret] = prev_page_count;
|
||||
/* update memory instance ptr and memory size */
|
||||
memory = module->default_memory;
|
||||
/* update memory size, no need to update memory ptr as
|
||||
it isn't changed in wasm_enlarge_memory */
|
||||
#if !defined(OS_ENABLE_HW_BOUND_CHECK) \
|
||||
|| WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0 \
|
||||
|| WASM_ENABLE_BULK_MEMORY != 0
|
||||
|
@ -3093,7 +3094,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
|
||||
bh_memcpy_s(
|
||||
(uint8 *)tbl_inst
|
||||
+ offsetof(WASMTableInstance, base_addr)
|
||||
+ offsetof(WASMTableInstance, elems)
|
||||
+ d * sizeof(uint32),
|
||||
(uint32)((tbl_inst->cur_size - d) * sizeof(uint32)),
|
||||
module->module->table_segments[elem_idx]
|
||||
|
@ -3141,16 +3142,15 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
/* if s >= d, copy from front to back */
|
||||
/* if s < d, copy from back to front */
|
||||
/* merge all together */
|
||||
bh_memmove_s(
|
||||
(uint8 *)dst_tbl_inst
|
||||
+ offsetof(WASMTableInstance, base_addr)
|
||||
+ d * sizeof(uint32),
|
||||
(uint32)((dst_tbl_inst->cur_size - d)
|
||||
* sizeof(uint32)),
|
||||
(uint8 *)src_tbl_inst
|
||||
+ offsetof(WASMTableInstance, base_addr)
|
||||
+ s * sizeof(uint32),
|
||||
(uint32)(n * sizeof(uint32)));
|
||||
bh_memmove_s((uint8 *)dst_tbl_inst
|
||||
+ offsetof(WASMTableInstance, elems)
|
||||
+ d * sizeof(uint32),
|
||||
(uint32)((dst_tbl_inst->cur_size - d)
|
||||
* sizeof(uint32)),
|
||||
(uint8 *)src_tbl_inst
|
||||
+ offsetof(WASMTableInstance, elems)
|
||||
+ s * sizeof(uint32),
|
||||
(uint32)(n * sizeof(uint32)));
|
||||
break;
|
||||
}
|
||||
case WASM_OP_TABLE_GROW:
|
||||
|
@ -3211,7 +3211,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
}
|
||||
|
||||
for (; n != 0; i++, n--) {
|
||||
((uint32 *)(tbl_inst->base_addr))[i] = fill_val;
|
||||
tbl_inst->elems[i] = fill_val;
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -3305,23 +3305,23 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
if (opcode == WASM_OP_ATOMIC_I32_LOAD8_U) {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(1);
|
||||
os_mutex_lock(&memory->mem_lock);
|
||||
os_mutex_lock(&module->e->mem_lock);
|
||||
readv = (uint32)(*(uint8 *)maddr);
|
||||
os_mutex_unlock(&memory->mem_lock);
|
||||
os_mutex_unlock(&module->e->mem_lock);
|
||||
}
|
||||
else if (opcode == WASM_OP_ATOMIC_I32_LOAD16_U) {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(2);
|
||||
os_mutex_lock(&memory->mem_lock);
|
||||
os_mutex_lock(&module->e->mem_lock);
|
||||
readv = (uint32)LOAD_U16(maddr);
|
||||
os_mutex_unlock(&memory->mem_lock);
|
||||
os_mutex_unlock(&module->e->mem_lock);
|
||||
}
|
||||
else {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(4);
|
||||
os_mutex_lock(&memory->mem_lock);
|
||||
os_mutex_lock(&module->e->mem_lock);
|
||||
readv = LOAD_I32(maddr);
|
||||
os_mutex_unlock(&memory->mem_lock);
|
||||
os_mutex_unlock(&module->e->mem_lock);
|
||||
}
|
||||
|
||||
PUSH_I32(readv);
|
||||
|
@ -3340,30 +3340,30 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
if (opcode == WASM_OP_ATOMIC_I64_LOAD8_U) {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(1);
|
||||
os_mutex_lock(&memory->mem_lock);
|
||||
os_mutex_lock(&module->e->mem_lock);
|
||||
readv = (uint64)(*(uint8 *)maddr);
|
||||
os_mutex_unlock(&memory->mem_lock);
|
||||
os_mutex_unlock(&module->e->mem_lock);
|
||||
}
|
||||
else if (opcode == WASM_OP_ATOMIC_I64_LOAD16_U) {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(2);
|
||||
os_mutex_lock(&memory->mem_lock);
|
||||
os_mutex_lock(&module->e->mem_lock);
|
||||
readv = (uint64)LOAD_U16(maddr);
|
||||
os_mutex_unlock(&memory->mem_lock);
|
||||
os_mutex_unlock(&module->e->mem_lock);
|
||||
}
|
||||
else if (opcode == WASM_OP_ATOMIC_I64_LOAD32_U) {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(4);
|
||||
os_mutex_lock(&memory->mem_lock);
|
||||
os_mutex_lock(&module->e->mem_lock);
|
||||
readv = (uint64)LOAD_U32(maddr);
|
||||
os_mutex_unlock(&memory->mem_lock);
|
||||
os_mutex_unlock(&module->e->mem_lock);
|
||||
}
|
||||
else {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(8);
|
||||
os_mutex_lock(&memory->mem_lock);
|
||||
os_mutex_lock(&module->e->mem_lock);
|
||||
readv = LOAD_I64(maddr);
|
||||
os_mutex_unlock(&memory->mem_lock);
|
||||
os_mutex_unlock(&module->e->mem_lock);
|
||||
}
|
||||
|
||||
PUSH_I64(readv);
|
||||
|
@ -3381,23 +3381,23 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
if (opcode == WASM_OP_ATOMIC_I32_STORE8) {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(1);
|
||||
os_mutex_lock(&memory->mem_lock);
|
||||
os_mutex_lock(&module->e->mem_lock);
|
||||
*(uint8 *)maddr = (uint8)sval;
|
||||
os_mutex_unlock(&memory->mem_lock);
|
||||
os_mutex_unlock(&module->e->mem_lock);
|
||||
}
|
||||
else if (opcode == WASM_OP_ATOMIC_I32_STORE16) {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(2);
|
||||
os_mutex_lock(&memory->mem_lock);
|
||||
os_mutex_lock(&module->e->mem_lock);
|
||||
STORE_U16(maddr, (uint16)sval);
|
||||
os_mutex_unlock(&memory->mem_lock);
|
||||
os_mutex_unlock(&module->e->mem_lock);
|
||||
}
|
||||
else {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(4);
|
||||
os_mutex_lock(&memory->mem_lock);
|
||||
os_mutex_lock(&module->e->mem_lock);
|
||||
STORE_U32(maddr, sval);
|
||||
os_mutex_unlock(&memory->mem_lock);
|
||||
os_mutex_unlock(&module->e->mem_lock);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -3415,30 +3415,30 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
if (opcode == WASM_OP_ATOMIC_I64_STORE8) {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(1);
|
||||
os_mutex_lock(&memory->mem_lock);
|
||||
os_mutex_lock(&module->e->mem_lock);
|
||||
*(uint8 *)maddr = (uint8)sval;
|
||||
os_mutex_unlock(&memory->mem_lock);
|
||||
os_mutex_unlock(&module->e->mem_lock);
|
||||
}
|
||||
else if (opcode == WASM_OP_ATOMIC_I64_STORE16) {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(2);
|
||||
os_mutex_lock(&memory->mem_lock);
|
||||
os_mutex_lock(&module->e->mem_lock);
|
||||
STORE_U16(maddr, (uint16)sval);
|
||||
os_mutex_unlock(&memory->mem_lock);
|
||||
os_mutex_unlock(&module->e->mem_lock);
|
||||
}
|
||||
else if (opcode == WASM_OP_ATOMIC_I64_STORE32) {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(4);
|
||||
os_mutex_lock(&memory->mem_lock);
|
||||
os_mutex_lock(&module->e->mem_lock);
|
||||
STORE_U32(maddr, (uint32)sval);
|
||||
os_mutex_unlock(&memory->mem_lock);
|
||||
os_mutex_unlock(&module->e->mem_lock);
|
||||
}
|
||||
else {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(8);
|
||||
os_mutex_lock(&memory->mem_lock);
|
||||
os_mutex_lock(&module->e->mem_lock);
|
||||
STORE_I64(maddr, sval);
|
||||
os_mutex_unlock(&memory->mem_lock);
|
||||
os_mutex_unlock(&module->e->mem_lock);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -3458,32 +3458,32 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
CHECK_ATOMIC_MEMORY_ACCESS(1);
|
||||
|
||||
expect = (uint8)expect;
|
||||
os_mutex_lock(&memory->mem_lock);
|
||||
os_mutex_lock(&module->e->mem_lock);
|
||||
readv = (uint32)(*(uint8 *)maddr);
|
||||
if (readv == expect)
|
||||
*(uint8 *)maddr = (uint8)(sval);
|
||||
os_mutex_unlock(&memory->mem_lock);
|
||||
os_mutex_unlock(&module->e->mem_lock);
|
||||
}
|
||||
else if (opcode == WASM_OP_ATOMIC_RMW_I32_CMPXCHG16_U) {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(2);
|
||||
|
||||
expect = (uint16)expect;
|
||||
os_mutex_lock(&memory->mem_lock);
|
||||
os_mutex_lock(&module->e->mem_lock);
|
||||
readv = (uint32)LOAD_U16(maddr);
|
||||
if (readv == expect)
|
||||
STORE_U16(maddr, (uint16)(sval));
|
||||
os_mutex_unlock(&memory->mem_lock);
|
||||
os_mutex_unlock(&module->e->mem_lock);
|
||||
}
|
||||
else {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(4);
|
||||
|
||||
os_mutex_lock(&memory->mem_lock);
|
||||
os_mutex_lock(&module->e->mem_lock);
|
||||
readv = LOAD_I32(maddr);
|
||||
if (readv == expect)
|
||||
STORE_U32(maddr, sval);
|
||||
os_mutex_unlock(&memory->mem_lock);
|
||||
os_mutex_unlock(&module->e->mem_lock);
|
||||
}
|
||||
PUSH_I32(readv);
|
||||
break;
|
||||
|
@ -3504,44 +3504,44 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
CHECK_ATOMIC_MEMORY_ACCESS(1);
|
||||
|
||||
expect = (uint8)expect;
|
||||
os_mutex_lock(&memory->mem_lock);
|
||||
os_mutex_lock(&module->e->mem_lock);
|
||||
readv = (uint64)(*(uint8 *)maddr);
|
||||
if (readv == expect)
|
||||
*(uint8 *)maddr = (uint8)(sval);
|
||||
os_mutex_unlock(&memory->mem_lock);
|
||||
os_mutex_unlock(&module->e->mem_lock);
|
||||
}
|
||||
else if (opcode == WASM_OP_ATOMIC_RMW_I64_CMPXCHG16_U) {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(2);
|
||||
|
||||
expect = (uint16)expect;
|
||||
os_mutex_lock(&memory->mem_lock);
|
||||
os_mutex_lock(&module->e->mem_lock);
|
||||
readv = (uint64)LOAD_U16(maddr);
|
||||
if (readv == expect)
|
||||
STORE_U16(maddr, (uint16)(sval));
|
||||
os_mutex_unlock(&memory->mem_lock);
|
||||
os_mutex_unlock(&module->e->mem_lock);
|
||||
}
|
||||
else if (opcode == WASM_OP_ATOMIC_RMW_I64_CMPXCHG32_U) {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(4);
|
||||
|
||||
expect = (uint32)expect;
|
||||
os_mutex_lock(&memory->mem_lock);
|
||||
os_mutex_lock(&module->e->mem_lock);
|
||||
readv = (uint64)LOAD_U32(maddr);
|
||||
if (readv == expect)
|
||||
STORE_U32(maddr, (uint32)(sval));
|
||||
os_mutex_unlock(&memory->mem_lock);
|
||||
os_mutex_unlock(&module->e->mem_lock);
|
||||
}
|
||||
else {
|
||||
CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr);
|
||||
CHECK_ATOMIC_MEMORY_ACCESS(8);
|
||||
|
||||
os_mutex_lock(&memory->mem_lock);
|
||||
os_mutex_lock(&module->e->mem_lock);
|
||||
readv = (uint64)LOAD_I64(maddr);
|
||||
if (readv == expect) {
|
||||
STORE_I64(maddr, sval);
|
||||
}
|
||||
os_mutex_unlock(&memory->mem_lock);
|
||||
os_mutex_unlock(&module->e->mem_lock);
|
||||
}
|
||||
PUSH_I64(readv);
|
||||
break;
|
||||
|
@ -3575,12 +3575,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
#endif
|
||||
fidx = read_uint32(frame_ip);
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
if (fidx >= module->function_count) {
|
||||
if (fidx >= module->e->function_count) {
|
||||
wasm_set_exception(module, "unknown function");
|
||||
goto got_exception;
|
||||
}
|
||||
#endif
|
||||
cur_func = module->functions + fidx;
|
||||
cur_func = module->e->functions + fidx;
|
||||
goto call_func_from_interp;
|
||||
}
|
||||
|
||||
|
@ -3592,12 +3592,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
#endif
|
||||
fidx = read_uint32(frame_ip);
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
if (fidx >= module->function_count) {
|
||||
if (fidx >= module->e->function_count) {
|
||||
wasm_set_exception(module, "unknown function");
|
||||
goto got_exception;
|
||||
}
|
||||
#endif
|
||||
cur_func = module->functions + fidx;
|
||||
cur_func = module->e->functions + fidx;
|
||||
goto call_func_from_return_call;
|
||||
}
|
||||
#endif /* WASM_ENABLE_TAIL_CALL */
|
||||
|
@ -3782,8 +3782,8 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
|||
cur_func = frame->function;
|
||||
UPDATE_ALL_FROM_FRAME();
|
||||
|
||||
/* update memory instance ptr and memory size */
|
||||
memory = module->default_memory;
|
||||
/* update memory size, no need to update memory ptr as
|
||||
it isn't changed in wasm_enlarge_memory */
|
||||
#if !defined(OS_ENABLE_HW_BOUND_CHECK) \
|
||||
|| WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0 \
|
||||
|| WASM_ENABLE_BULK_MEMORY != 0
|
||||
|
|
|
@ -18,6 +18,9 @@
|
|||
#include "../fast-jit/jit_compiler.h"
|
||||
#include "../fast-jit/jit_codecache.h"
|
||||
#endif
|
||||
#if WASM_ENABLE_JIT != 0
|
||||
#include "../compilation/aot_llvm.h"
|
||||
#endif
|
||||
|
||||
/* Read a value of given type from the address pointed to by the given
|
||||
pointer and increase the pointer to the position just after the
|
||||
|
@ -2923,7 +2926,6 @@ fail:
|
|||
return false;
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_FAST_JIT != 0
|
||||
static void
|
||||
calculate_global_data_offset(WASMModule *module)
|
||||
{
|
||||
|
@ -2933,17 +2935,127 @@ calculate_global_data_offset(WASMModule *module)
|
|||
for (i = 0; i < module->import_global_count; i++) {
|
||||
WASMGlobalImport *import_global =
|
||||
&((module->import_globals + i)->u.global);
|
||||
#if WASM_ENABLE_FAST_JIT != 0
|
||||
import_global->data_offset = data_offset;
|
||||
#endif
|
||||
data_offset += wasm_value_type_size(import_global->type);
|
||||
}
|
||||
|
||||
for (i = 0; i < module->global_count; i++) {
|
||||
WASMGlobal *global = module->globals + i;
|
||||
#if WASM_ENABLE_FAST_JIT != 0
|
||||
global->data_offset = data_offset;
|
||||
#endif
|
||||
data_offset += wasm_value_type_size(global->type);
|
||||
}
|
||||
|
||||
module->global_data_size = data_offset;
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_JIT != 0
|
||||
static bool
|
||||
compile_llvm_jit_functions(WASMModule *module, char *error_buf,
|
||||
uint32 error_buf_size)
|
||||
{
|
||||
AOTCompOption option = { 0 };
|
||||
char func_name[32], *aot_last_error;
|
||||
uint64 size;
|
||||
uint32 i;
|
||||
|
||||
size = sizeof(void *) * (uint64)module->function_count;
|
||||
if (size > 0
|
||||
&& !(module->func_ptrs =
|
||||
loader_malloc(size, error_buf, error_buf_size))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
module->comp_data = aot_create_comp_data(module);
|
||||
if (!module->comp_data) {
|
||||
aot_last_error = aot_get_last_error();
|
||||
bh_assert(aot_last_error != NULL);
|
||||
set_error_buf(error_buf, error_buf_size, aot_last_error);
|
||||
return false;
|
||||
}
|
||||
|
||||
option.is_jit_mode = true;
|
||||
option.opt_level = 3;
|
||||
option.size_level = 3;
|
||||
#if WASM_ENABLE_BULK_MEMORY != 0
|
||||
option.enable_bulk_memory = true;
|
||||
#endif
|
||||
#if WASM_ENABLE_THREAD_MGR != 0
|
||||
option.enable_thread_mgr = true;
|
||||
#endif
|
||||
#if WASM_ENABLE_TAIL_CALL != 0
|
||||
option.enable_tail_call = true;
|
||||
#endif
|
||||
#if WASM_ENABLE_SIMD != 0
|
||||
option.enable_simd = true;
|
||||
#endif
|
||||
#if WASM_ENABLE_REF_TYPES != 0
|
||||
option.enable_ref_types = true;
|
||||
#endif
|
||||
option.enable_aux_stack_check = true;
|
||||
#if (WASM_ENABLE_PERF_PROFILING != 0) || (WASM_ENABLE_DUMP_CALL_STACK != 0)
|
||||
option.enable_aux_stack_frame = true;
|
||||
#endif
|
||||
|
||||
module->comp_ctx = aot_create_comp_context(module->comp_data, &option);
|
||||
if (!module->comp_ctx) {
|
||||
aot_last_error = aot_get_last_error();
|
||||
bh_assert(aot_last_error != NULL);
|
||||
set_error_buf(error_buf, error_buf_size, aot_last_error);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!aot_compile_wasm(module->comp_ctx)) {
|
||||
aot_last_error = aot_get_last_error();
|
||||
bh_assert(aot_last_error != NULL);
|
||||
set_error_buf(error_buf, error_buf_size, aot_last_error);
|
||||
return false;
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_LAZY_JIT != 0
|
||||
for (i = 0; i < module->comp_data->func_count; i++) {
|
||||
LLVMErrorRef error;
|
||||
LLVMOrcJITTargetAddress func_addr = 0;
|
||||
|
||||
snprintf(func_name, sizeof(func_name), "%s%d", AOT_FUNC_PREFIX, i);
|
||||
if ((error = LLVMOrcLLJITLookup(module->comp_ctx->orc_lazyjit,
|
||||
&func_addr, func_name))) {
|
||||
char *err_msg = LLVMGetErrorMessage(error);
|
||||
set_error_buf_v(error_buf, error_buf_size,
|
||||
"failed to compile orc jit function: %s", err_msg);
|
||||
LLVMDisposeErrorMessage(err_msg);
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* No need to lock the func_ptr[func_idx] here as it is basic
|
||||
* data type, the load/store for it can be finished by one cpu
|
||||
* instruction, and there can be only one cpu instruction
|
||||
* loading/storing at the same time.
|
||||
*/
|
||||
module->func_ptrs[i] = (void *)func_addr;
|
||||
module->functions[i]->llvm_jit_func_ptr = (void *)func_addr;
|
||||
}
|
||||
#else
|
||||
/* Resolve function addresses */
|
||||
bh_assert(module->comp_ctx->exec_engine);
|
||||
for (i = 0; i < module->comp_data->func_count; i++) {
|
||||
snprintf(func_name, sizeof(func_name), "%s%d", AOT_FUNC_PREFIX, i);
|
||||
if (!(module->func_ptrs[i] = (void *)LLVMGetFunctionAddress(
|
||||
module->comp_ctx->exec_engine, func_name))) {
|
||||
set_error_buf(error_buf, error_buf_size,
|
||||
"failed to compile llvm mc jit function");
|
||||
return false;
|
||||
}
|
||||
module->functions[i]->llvm_jit_func_ptr = module->func_ptrs[i];
|
||||
}
|
||||
#endif /* end of WASM_ENABLE_LAZY_JIT != 0 */
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif /* end of WASM_ENABLE_JIT != 0 */
|
||||
|
||||
static bool
|
||||
wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func,
|
||||
|
@ -3352,9 +3464,9 @@ load_from_sections(WASMModule *module, WASMSection *sections,
|
|||
#endif
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_FAST_JIT != 0
|
||||
calculate_global_data_offset(module);
|
||||
|
||||
#if WASM_ENABLE_FAST_JIT != 0
|
||||
if (module->function_count
|
||||
&& !(module->fast_jit_func_ptrs =
|
||||
loader_malloc(sizeof(void *) * module->function_count,
|
||||
|
@ -3367,6 +3479,12 @@ load_from_sections(WASMModule *module, WASMSection *sections,
|
|||
}
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_JIT != 0
|
||||
if (!compile_llvm_jit_functions(module, error_buf, error_buf_size)) {
|
||||
return false;
|
||||
}
|
||||
#endif /* end of WASM_ENABLE_JIT != 0 */
|
||||
|
||||
#if WASM_ENABLE_MEMORY_TRACING != 0
|
||||
wasm_runtime_dump_module_mem_consumption((WASMModuleCommon *)module);
|
||||
#endif
|
||||
|
@ -3900,6 +4018,15 @@ wasm_loader_unload(WASMModule *module)
|
|||
}
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_JIT != 0
|
||||
if (module->func_ptrs)
|
||||
wasm_runtime_free(module->func_ptrs);
|
||||
if (module->comp_ctx)
|
||||
aot_destroy_comp_context(module->comp_ctx);
|
||||
if (module->comp_data)
|
||||
aot_destroy_comp_data(module->comp_data);
|
||||
#endif
|
||||
|
||||
wasm_runtime_free(module);
|
||||
}
|
||||
|
||||
|
@ -6756,8 +6883,7 @@ re_scan:
|
|||
}
|
||||
block_type.is_value_type = false;
|
||||
block_type.u.type = module->types[type_index];
|
||||
#if WASM_ENABLE_FAST_INTERP == 0 && WASM_ENABLE_WAMR_COMPILER == 0 \
|
||||
&& WASM_ENABLE_JIT == 0
|
||||
#if WASM_ENABLE_FAST_INTERP == 0
|
||||
/* If block use type index as block type, change the opcode
|
||||
* to new extended opcode so that interpreter can resolve
|
||||
* the block quickly.
|
||||
|
|
|
@ -15,6 +15,9 @@
|
|||
#include "../fast-jit/jit_compiler.h"
|
||||
#include "../fast-jit/jit_codecache.h"
|
||||
#endif
|
||||
#if WASM_ENABLE_JIT != 0
|
||||
#include "../compilation/aot_llvm.h"
|
||||
#endif
|
||||
|
||||
/* Read a value of given type from the address pointed to by the given
|
||||
pointer and increase the pointer to the position just after the
|
||||
|
@ -961,6 +964,11 @@ load_function_section(const uint8 *buf, const uint8 *buf_end,
|
|||
read_leb_uint32(p, p_end, type_index);
|
||||
bh_assert(type_index < module->type_count);
|
||||
|
||||
#if (WASM_ENABLE_WAMR_COMPILER != 0) || (WASM_ENABLE_JIT != 0)
|
||||
type_index = wasm_get_smallest_type_idx(
|
||||
module->types, module->type_count, type_index);
|
||||
#endif
|
||||
|
||||
read_leb_uint32(p_code, buf_code_end, code_size);
|
||||
bh_assert(code_size > 0 && p_code + code_size <= buf_code_end);
|
||||
|
||||
|
@ -1749,6 +1757,137 @@ load_user_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
|
|||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
calculate_global_data_offset(WASMModule *module)
|
||||
{
|
||||
uint32 i, data_offset;
|
||||
|
||||
data_offset = 0;
|
||||
for (i = 0; i < module->import_global_count; i++) {
|
||||
WASMGlobalImport *import_global =
|
||||
&((module->import_globals + i)->u.global);
|
||||
#if WASM_ENABLE_FAST_JIT != 0
|
||||
import_global->data_offset = data_offset;
|
||||
#endif
|
||||
data_offset += wasm_value_type_size(import_global->type);
|
||||
}
|
||||
|
||||
for (i = 0; i < module->global_count; i++) {
|
||||
WASMGlobal *global = module->globals + i;
|
||||
#if WASM_ENABLE_FAST_JIT != 0
|
||||
global->data_offset = data_offset;
|
||||
#endif
|
||||
data_offset += wasm_value_type_size(global->type);
|
||||
}
|
||||
|
||||
module->global_data_size = data_offset;
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_JIT != 0
|
||||
static bool
|
||||
compile_llvm_jit_functions(WASMModule *module, char *error_buf,
|
||||
uint32 error_buf_size)
|
||||
{
|
||||
AOTCompOption option = { 0 };
|
||||
char func_name[32], *aot_last_error;
|
||||
uint64 size;
|
||||
uint32 i;
|
||||
|
||||
size = sizeof(void *) * (uint64)module->function_count;
|
||||
if (size > 0
|
||||
&& !(module->func_ptrs =
|
||||
loader_malloc(size, error_buf, error_buf_size))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
module->comp_data = aot_create_comp_data(module);
|
||||
if (!module->comp_data) {
|
||||
aot_last_error = aot_get_last_error();
|
||||
bh_assert(aot_last_error != NULL);
|
||||
set_error_buf(error_buf, error_buf_size, aot_last_error);
|
||||
return false;
|
||||
}
|
||||
|
||||
option.is_jit_mode = true;
|
||||
option.opt_level = 3;
|
||||
option.size_level = 3;
|
||||
#if WASM_ENABLE_BULK_MEMORY != 0
|
||||
option.enable_bulk_memory = true;
|
||||
#endif
|
||||
#if WASM_ENABLE_THREAD_MGR != 0
|
||||
option.enable_thread_mgr = true;
|
||||
#endif
|
||||
#if WASM_ENABLE_TAIL_CALL != 0
|
||||
option.enable_tail_call = true;
|
||||
#endif
|
||||
#if WASM_ENABLE_SIMD != 0
|
||||
option.enable_simd = true;
|
||||
#endif
|
||||
#if WASM_ENABLE_REF_TYPES != 0
|
||||
option.enable_ref_types = true;
|
||||
#endif
|
||||
option.enable_aux_stack_check = true;
|
||||
#if (WASM_ENABLE_PERF_PROFILING != 0) || (WASM_ENABLE_DUMP_CALL_STACK != 0)
|
||||
option.enable_aux_stack_frame = true;
|
||||
#endif
|
||||
|
||||
module->comp_ctx = aot_create_comp_context(module->comp_data, &option);
|
||||
if (!module->comp_ctx) {
|
||||
aot_last_error = aot_get_last_error();
|
||||
bh_assert(aot_last_error != NULL);
|
||||
set_error_buf(error_buf, error_buf_size, aot_last_error);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!aot_compile_wasm(module->comp_ctx)) {
|
||||
aot_last_error = aot_get_last_error();
|
||||
bh_assert(aot_last_error != NULL);
|
||||
set_error_buf(error_buf, error_buf_size, aot_last_error);
|
||||
return false;
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_LAZY_JIT != 0
|
||||
for (i = 0; i < module->comp_data->func_count; i++) {
|
||||
LLVMErrorRef error;
|
||||
LLVMOrcJITTargetAddress func_addr = 0;
|
||||
|
||||
snprintf(func_name, sizeof(func_name), "%s%d", AOT_FUNC_PREFIX, i);
|
||||
if ((error = LLVMOrcLLJITLookup(module->comp_ctx->orc_lazyjit,
|
||||
&func_addr, func_name))) {
|
||||
char *err_msg = LLVMGetErrorMessage(error);
|
||||
set_error_buf_v(error_buf, error_buf_size,
|
||||
"failed to compile orc jit function: %s", err_msg);
|
||||
LLVMDisposeErrorMessage(err_msg);
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* No need to lock the func_ptr[func_idx] here as it is basic
|
||||
* data type, the load/store for it can be finished by one cpu
|
||||
* instruction, and there can be only one cpu instruction
|
||||
* loading/storing at the same time.
|
||||
*/
|
||||
module->func_ptrs[i] = (void *)func_addr;
|
||||
module->functions[i]->llvm_jit_func_ptr = (void *)func_addr;
|
||||
}
|
||||
#else
|
||||
/* Resolve function addresses */
|
||||
bh_assert(module->comp_ctx->exec_engine);
|
||||
for (i = 0; i < module->comp_data->func_count; i++) {
|
||||
snprintf(func_name, sizeof(func_name), "%s%d", AOT_FUNC_PREFIX, i);
|
||||
if (!(module->func_ptrs[i] = (void *)LLVMGetFunctionAddress(
|
||||
module->comp_ctx->exec_engine, func_name))) {
|
||||
set_error_buf(error_buf, error_buf_size,
|
||||
"failed to compile llvm mc jit function");
|
||||
return false;
|
||||
}
|
||||
module->functions[i]->llvm_jit_func_ptr = module->func_ptrs[i];
|
||||
}
|
||||
#endif /* end of WASM_ENABLE_LAZY_JIT != 0 */
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif /* end of WASM_ENABLE_JIT != 0 */
|
||||
|
||||
#if WASM_ENABLE_REF_TYPES != 0
|
||||
static bool
|
||||
get_table_elem_type(const WASMModule *module, uint32 table_idx,
|
||||
|
@ -2185,6 +2324,8 @@ load_from_sections(WASMModule *module, WASMSection *sections,
|
|||
}
|
||||
}
|
||||
|
||||
calculate_global_data_offset(module);
|
||||
|
||||
#if WASM_ENABLE_FAST_JIT != 0
|
||||
if (!(module->fast_jit_func_ptrs =
|
||||
loader_malloc(sizeof(void *) * module->function_count, error_buf,
|
||||
|
@ -2197,6 +2338,12 @@ load_from_sections(WASMModule *module, WASMSection *sections,
|
|||
}
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_JIT != 0
|
||||
if (!compile_llvm_jit_functions(module, error_buf, error_buf_size)) {
|
||||
return false;
|
||||
}
|
||||
#endif /* end of WASM_ENABLE_JIT != 0 */
|
||||
|
||||
#if WASM_ENABLE_MEMORY_TRACING != 0
|
||||
wasm_runtime_dump_module_mem_consumption(module);
|
||||
#endif
|
||||
|
@ -2526,6 +2673,15 @@ wasm_loader_unload(WASMModule *module)
|
|||
}
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_JIT != 0
|
||||
if (module->func_ptrs)
|
||||
wasm_runtime_free(module->func_ptrs);
|
||||
if (module->comp_ctx)
|
||||
aot_destroy_comp_context(module->comp_ctx);
|
||||
if (module->comp_data)
|
||||
aot_destroy_comp_data(module->comp_data);
|
||||
#endif
|
||||
|
||||
wasm_runtime_free(module);
|
||||
}
|
||||
|
||||
|
@ -5035,8 +5191,7 @@ re_scan:
|
|||
bh_assert(type_index < module->type_count);
|
||||
block_type.is_value_type = false;
|
||||
block_type.u.type = module->types[type_index];
|
||||
#if WASM_ENABLE_FAST_INTERP == 0 && WASM_ENABLE_WAMR_COMPILER == 0 \
|
||||
&& WASM_ENABLE_JIT == 0
|
||||
#if WASM_ENABLE_FAST_INTERP == 0
|
||||
/* If block use type index as block type, change the opcode
|
||||
* to new extended opcode so that interpreter can resolve
|
||||
* the block quickly.
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -21,6 +21,53 @@ typedef struct WASMMemoryInstance WASMMemoryInstance;
|
|||
typedef struct WASMTableInstance WASMTableInstance;
|
||||
typedef struct WASMGlobalInstance WASMGlobalInstance;
|
||||
|
||||
/**
|
||||
* When LLVM JIT, WAMR compiler or AOT is enabled, we should ensure that
|
||||
* some offsets of the same field in the interpreter module instance and
|
||||
* aot module instance are the same, so that the LLVM JITed/AOTed code
|
||||
* can smoothly access the interpreter module instance.
|
||||
* Same for the memory instance and table instance.
|
||||
* We use the macro DefPointer to define some related pointer fields.
|
||||
*/
|
||||
#if (WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0 \
|
||||
|| WASM_ENABLE_AOT != 0) \
|
||||
&& UINTPTR_MAX == UINT32_MAX
|
||||
/* Add u32 padding if LLVM JIT, WAMR compiler or AOT is enabled on
|
||||
32-bit platform */
|
||||
#define DefPointer(type, field) \
|
||||
type field; \
|
||||
uint32 field##_padding
|
||||
#else
|
||||
#define DefPointer(type, field) type field
|
||||
#endif
|
||||
|
||||
typedef enum WASMExceptionID {
|
||||
EXCE_UNREACHABLE = 0,
|
||||
EXCE_OUT_OF_MEMORY,
|
||||
EXCE_OUT_OF_BOUNDS_MEMORY_ACCESS,
|
||||
EXCE_INTEGER_OVERFLOW,
|
||||
EXCE_INTEGER_DIVIDE_BY_ZERO,
|
||||
EXCE_INVALID_CONVERSION_TO_INTEGER,
|
||||
EXCE_INVALID_FUNCTION_TYPE_INDEX,
|
||||
EXCE_INVALID_FUNCTION_INDEX,
|
||||
EXCE_UNDEFINED_ELEMENT,
|
||||
EXCE_UNINITIALIZED_ELEMENT,
|
||||
EXCE_CALL_UNLINKED_IMPORT_FUNC,
|
||||
EXCE_NATIVE_STACK_OVERFLOW,
|
||||
EXCE_UNALIGNED_ATOMIC,
|
||||
EXCE_AUX_STACK_OVERFLOW,
|
||||
EXCE_AUX_STACK_UNDERFLOW,
|
||||
EXCE_OUT_OF_BOUNDS_TABLE_ACCESS,
|
||||
EXCE_OPERAND_STACK_OVERFLOW,
|
||||
EXCE_ALREADY_THROWN,
|
||||
EXCE_NUM,
|
||||
} WASMExceptionID;
|
||||
|
||||
typedef union {
|
||||
uint64 u64;
|
||||
uint32 u32[2];
|
||||
} MemBound;
|
||||
|
||||
struct WASMMemoryInstance {
|
||||
/* Module type */
|
||||
uint32 module_type;
|
||||
|
@ -35,59 +82,40 @@ struct WASMMemoryInstance {
|
|||
uint32 max_page_count;
|
||||
/* Memory data size */
|
||||
uint32 memory_data_size;
|
||||
|
||||
/**
|
||||
* Memory data begin address, Note:
|
||||
* the app-heap might be inserted in to the linear memory,
|
||||
* when memory is re-allocated, the heap data and memory data
|
||||
* must be copied to new memory also
|
||||
*/
|
||||
uint8 *memory_data;
|
||||
DefPointer(uint8 *, memory_data);
|
||||
/* Memory data end address */
|
||||
uint8 *memory_data_end;
|
||||
DefPointer(uint8 *, memory_data_end);
|
||||
|
||||
/* Heap data base address */
|
||||
uint8 *heap_data;
|
||||
DefPointer(uint8 *, heap_data);
|
||||
/* Heap data end address */
|
||||
uint8 *heap_data_end;
|
||||
DefPointer(uint8 *, heap_data_end);
|
||||
/* The heap created */
|
||||
void *heap_handle;
|
||||
DefPointer(void *, heap_handle);
|
||||
|
||||
#if WASM_ENABLE_SHARED_MEMORY != 0
|
||||
/* mutex lock for the memory, used in atomic operation */
|
||||
korp_mutex mem_lock;
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_FAST_JIT != 0
|
||||
#if UINTPTR_MAX == UINT64_MAX
|
||||
uint64 mem_bound_check_1byte;
|
||||
uint64 mem_bound_check_2bytes;
|
||||
uint64 mem_bound_check_4bytes;
|
||||
uint64 mem_bound_check_8bytes;
|
||||
uint64 mem_bound_check_16bytes;
|
||||
#else
|
||||
uint32 mem_bound_check_1byte;
|
||||
uint32 mem_bound_check_2bytes;
|
||||
uint32 mem_bound_check_4bytes;
|
||||
uint32 mem_bound_check_8bytes;
|
||||
uint32 mem_bound_check_16bytes;
|
||||
#endif
|
||||
#if WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0 \
|
||||
|| WASM_ENABLE_WAMR_COMPILER != 0 || WASM_ENABLE_AOT != 0
|
||||
MemBound mem_bound_check_1byte;
|
||||
MemBound mem_bound_check_2bytes;
|
||||
MemBound mem_bound_check_4bytes;
|
||||
MemBound mem_bound_check_8bytes;
|
||||
MemBound mem_bound_check_16bytes;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct WASMTableInstance {
|
||||
/* The element type, VALUE_TYPE_FUNCREF/EXTERNREF currently */
|
||||
uint8 elem_type;
|
||||
/* Current size */
|
||||
uint32 cur_size;
|
||||
/* Maximum size */
|
||||
uint32 max_size;
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
/* just for import, keep the reference here */
|
||||
WASMTableInstance *table_inst_linked;
|
||||
#endif
|
||||
/* Base address */
|
||||
uint8 base_addr[1];
|
||||
/* Table elements */
|
||||
uint32 elems[1];
|
||||
};
|
||||
|
||||
struct WASMGlobalInstance {
|
||||
|
@ -149,7 +177,6 @@ typedef struct WASMExportFuncInstance {
|
|||
WASMFunctionInstance *function;
|
||||
} WASMExportFuncInstance;
|
||||
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
typedef struct WASMExportGlobInstance {
|
||||
char *name;
|
||||
WASMGlobalInstance *global;
|
||||
|
@ -164,8 +191,40 @@ typedef struct WASMExportMemInstance {
|
|||
char *name;
|
||||
WASMMemoryInstance *memory;
|
||||
} WASMExportMemInstance;
|
||||
|
||||
/* Extra info of WASM module instance for interpreter/jit mode */
|
||||
typedef struct WASMModuleInstanceExtra {
|
||||
WASMGlobalInstance *globals;
|
||||
WASMFunctionInstance *functions;
|
||||
|
||||
uint32 global_count;
|
||||
uint32 function_count;
|
||||
|
||||
WASMFunctionInstance *start_function;
|
||||
WASMFunctionInstance *malloc_function;
|
||||
WASMFunctionInstance *free_function;
|
||||
WASMFunctionInstance *retain_function;
|
||||
|
||||
#if WASM_ENABLE_SHARED_MEMORY != 0
|
||||
/* lock for shared memory atomic operations */
|
||||
korp_mutex mem_lock;
|
||||
bool mem_lock_inited;
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
bh_list sub_module_inst_list_head;
|
||||
bh_list *sub_module_inst_list;
|
||||
/* linked table instances of import table instances */
|
||||
WASMTableInstance **table_insts_linked;
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_MEMORY_PROFILING != 0
|
||||
uint32 max_aux_stack_used;
|
||||
#endif
|
||||
} WASMModuleInstanceExtra;
|
||||
|
||||
struct AOTFuncPerfProfInfo;
|
||||
|
||||
struct WASMModuleInstance {
|
||||
/* Module instance type, for module instance loaded from
|
||||
WASM bytecode binary, this field is Wasm_Module_Bytecode;
|
||||
|
@ -175,78 +234,82 @@ struct WASMModuleInstance {
|
|||
uint32 module_type;
|
||||
|
||||
uint32 memory_count;
|
||||
DefPointer(WASMMemoryInstance **, memories);
|
||||
|
||||
/* global and table info */
|
||||
uint32 global_data_size;
|
||||
uint32 table_count;
|
||||
uint32 global_count;
|
||||
uint32 function_count;
|
||||
DefPointer(uint8 *, global_data);
|
||||
/* For AOTModuleInstance, it denotes `AOTTableInstance *` */
|
||||
DefPointer(WASMTableInstance **, tables);
|
||||
|
||||
/* import func ptrs + llvm jit func ptrs */
|
||||
DefPointer(void **, func_ptrs);
|
||||
|
||||
/* function type indexes */
|
||||
DefPointer(uint32 *, func_type_indexes);
|
||||
|
||||
uint32 export_func_count;
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
uint32 export_glob_count;
|
||||
uint32 export_mem_count;
|
||||
uint32 export_tab_count;
|
||||
#endif
|
||||
|
||||
/* Array of function pointers to import functions */
|
||||
void **import_func_ptrs;
|
||||
#if WASM_ENABLE_FAST_JIT != 0
|
||||
/* point to JITed functions */
|
||||
void **fast_jit_func_ptrs;
|
||||
uint32 *func_type_indexes;
|
||||
#endif
|
||||
|
||||
WASMMemoryInstance **memories;
|
||||
WASMTableInstance **tables;
|
||||
WASMGlobalInstance *globals;
|
||||
WASMFunctionInstance *functions;
|
||||
|
||||
WASMExportFuncInstance *export_functions;
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
WASMExportGlobInstance *export_globals;
|
||||
WASMExportMemInstance *export_memories;
|
||||
WASMExportTabInstance *export_tables;
|
||||
#endif
|
||||
|
||||
WASMMemoryInstance *default_memory;
|
||||
WASMTableInstance *default_table;
|
||||
/* Global data of global instances */
|
||||
uint8 *global_data;
|
||||
|
||||
WASMFunctionInstance *start_function;
|
||||
WASMFunctionInstance *malloc_function;
|
||||
WASMFunctionInstance *free_function;
|
||||
WASMFunctionInstance *retain_function;
|
||||
|
||||
WASMModule *module;
|
||||
|
||||
#if WASM_ENABLE_LIBC_WASI != 0
|
||||
WASIContext *wasi_ctx;
|
||||
#endif
|
||||
|
||||
WASMExecEnv *exec_env_singleton;
|
||||
|
||||
/* Default WASM stack size of threads of this Module instance. */
|
||||
uint32 default_wasm_stack_size;
|
||||
uint32 export_global_count;
|
||||
uint32 export_memory_count;
|
||||
uint32 export_table_count;
|
||||
/* For AOTModuleInstance, it denotes `AOTFunctionInstance *` */
|
||||
DefPointer(WASMExportFuncInstance *, export_functions);
|
||||
DefPointer(WASMExportGlobInstance *, export_globals);
|
||||
DefPointer(WASMExportMemInstance *, export_memories);
|
||||
DefPointer(WASMExportTabInstance *, export_tables);
|
||||
|
||||
/* The exception buffer of wasm interpreter for current thread. */
|
||||
char cur_exception[128];
|
||||
|
||||
#if WASM_ENABLE_DUMP_CALL_STACK != 0
|
||||
Vector *frames;
|
||||
#endif
|
||||
/* The WASM module or AOT module, for AOTModuleInstance,
|
||||
it denotes `AOTModule *` */
|
||||
DefPointer(WASMModule *, module);
|
||||
|
||||
/* The custom data that can be set/get by
|
||||
* wasm_set_custom_data/wasm_get_custom_data */
|
||||
void *custom_data;
|
||||
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
/* TODO: add mutex for mutli-threads? */
|
||||
bh_list sub_module_inst_list_head;
|
||||
bh_list *sub_module_inst_list;
|
||||
#if WASM_ENABLE_LIBC_WASI
|
||||
/* WASI context */
|
||||
DefPointer(WASIContext *, wasi_ctx);
|
||||
#else
|
||||
DefPointer(void *, wasi_ctx);
|
||||
#endif
|
||||
DefPointer(WASMExecEnv *, exec_env_singleton);
|
||||
/* Array of function pointers to import functions,
|
||||
not available in AOTModuleInstance */
|
||||
DefPointer(void **, import_func_ptrs);
|
||||
/* Array of function pointers to fast jit functions,
|
||||
not available in AOTModuleInstance */
|
||||
DefPointer(void **, fast_jit_func_ptrs);
|
||||
/* The custom data that can be set/get by wasm_{get|set}_custom_data */
|
||||
DefPointer(void *, custom_data);
|
||||
/* Stack frames, used in call stack dump and perf profiling */
|
||||
DefPointer(Vector *, frames);
|
||||
/* Function performance profiling info list, only available
|
||||
in AOTModuleInstance */
|
||||
DefPointer(struct AOTFuncPerfProfInfo *, func_perf_profilings);
|
||||
/* WASM/AOT module extra info, for AOTModuleInstance,
|
||||
it denotes `AOTModuleInstanceExtra *` */
|
||||
DefPointer(WASMModuleInstanceExtra *, e);
|
||||
|
||||
#if WASM_ENABLE_MEMORY_PROFILING != 0
|
||||
uint32 max_aux_stack_used;
|
||||
#endif
|
||||
/* Default WASM operand stack size */
|
||||
uint32 default_wasm_stack_size;
|
||||
uint32 reserved[3];
|
||||
|
||||
/*
|
||||
* +------------------------------+ <-- memories
|
||||
* | WASMMemoryInstance[mem_count], mem_count is always 1 for LLVM JIT/AOT
|
||||
* +------------------------------+ <-- global_data
|
||||
* | global data
|
||||
* +------------------------------+ <-- tables
|
||||
* | WASMTableInstance[table_count]
|
||||
* +------------------------------+ <-- e
|
||||
* | WASMModuleInstanceExtra
|
||||
* +------------------------------+
|
||||
*/
|
||||
union {
|
||||
uint64 _make_it_8_byte_aligned_;
|
||||
WASMMemoryInstance memory_instances[1];
|
||||
uint8 bytes[1];
|
||||
} global_table_data;
|
||||
};
|
||||
|
||||
struct WASMInterpFrame;
|
||||
|
@ -342,12 +405,12 @@ wasm_create_exec_env_and_call_function(WASMModuleInstance *module_inst,
|
|||
WASMFunctionInstance *function,
|
||||
unsigned argc, uint32 argv[]);
|
||||
|
||||
bool
|
||||
wasm_create_exec_env_singleton(WASMModuleInstance *module_inst);
|
||||
|
||||
void
|
||||
wasm_set_exception(WASMModuleInstance *module, const char *exception);
|
||||
|
||||
void
|
||||
wasm_set_exception_with_id(WASMModuleInstance *module_inst, uint32 id);
|
||||
|
||||
const char *
|
||||
wasm_get_exception(WASMModuleInstance *module);
|
||||
|
||||
|
@ -366,45 +429,25 @@ uint32
|
|||
wasm_module_dup_data(WASMModuleInstance *module_inst, const char *src,
|
||||
uint32 size);
|
||||
|
||||
/**
|
||||
* Check whether the app address and the buf is inside the linear memory,
|
||||
* and convert the app address into native address
|
||||
*/
|
||||
bool
|
||||
wasm_validate_app_addr(WASMModuleInstance *module_inst, uint32 app_offset,
|
||||
uint32 size);
|
||||
wasm_check_app_addr_and_convert(WASMModuleInstance *module_inst, bool is_str,
|
||||
uint32 app_buf_addr, uint32 app_buf_size,
|
||||
void **p_native_addr);
|
||||
|
||||
WASMMemoryInstance *
|
||||
wasm_get_default_memory(WASMModuleInstance *module_inst);
|
||||
|
||||
bool
|
||||
wasm_validate_app_str_addr(WASMModuleInstance *module_inst, uint32 app_offset);
|
||||
|
||||
bool
|
||||
wasm_validate_native_addr(WASMModuleInstance *module_inst, void *native_ptr,
|
||||
uint32 size);
|
||||
|
||||
void *
|
||||
wasm_addr_app_to_native(WASMModuleInstance *module_inst, uint32 app_offset);
|
||||
|
||||
uint32
|
||||
wasm_addr_native_to_app(WASMModuleInstance *module_inst, void *native_ptr);
|
||||
|
||||
bool
|
||||
wasm_get_app_addr_range(WASMModuleInstance *module_inst, uint32 app_offset,
|
||||
uint32 *p_app_start_offset, uint32 *p_app_end_offset);
|
||||
|
||||
bool
|
||||
wasm_get_native_addr_range(WASMModuleInstance *module_inst, uint8 *native_ptr,
|
||||
uint8 **p_native_start_addr,
|
||||
uint8 **p_native_end_addr);
|
||||
|
||||
bool
|
||||
wasm_enlarge_memory(WASMModuleInstance *module, uint32 inc_page_count);
|
||||
wasm_enlarge_memory(WASMModuleInstance *module_inst, uint32 inc_page_count);
|
||||
|
||||
bool
|
||||
wasm_call_indirect(WASMExecEnv *exec_env, uint32 tbl_idx, uint32 elem_idx,
|
||||
uint32 argc, uint32 argv[]);
|
||||
|
||||
#if WASM_ENABLE_FAST_JIT != 0
|
||||
bool
|
||||
jit_call_indirect(WASMExecEnv *exec_env, uint32 tbl_idx, uint32 elem_idx,
|
||||
uint32 type_idx, uint32 argc, uint32 argv[]);
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_THREAD_MGR != 0
|
||||
bool
|
||||
wasm_set_aux_stack(WASMExecEnv *exec_env, uint32 start_offset, uint32 size);
|
||||
|
@ -413,16 +456,6 @@ bool
|
|||
wasm_get_aux_stack(WASMExecEnv *exec_env, uint32 *start_offset, uint32 *size);
|
||||
#endif
|
||||
|
||||
#ifdef OS_ENABLE_HW_BOUND_CHECK
|
||||
#ifndef BH_PLATFORM_WINDOWS
|
||||
void
|
||||
wasm_signal_handler(WASMSignalInfo *sig_info);
|
||||
#else
|
||||
LONG
|
||||
wasm_exception_handler(WASMSignalInfo *sig_info);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void
|
||||
wasm_get_module_mem_consumption(const WASMModule *module,
|
||||
WASMModuleMemConsumption *mem_conspn);
|
||||
|
@ -456,13 +489,14 @@ wasm_enlarge_table(WASMModuleInstance *module_inst, uint32 table_idx,
|
|||
#endif /* WASM_ENABLE_REF_TYPES != 0 */
|
||||
|
||||
static inline WASMTableInstance *
|
||||
wasm_get_table_inst(const WASMModuleInstance *module_inst, const uint32 tbl_idx)
|
||||
wasm_get_table_inst(const WASMModuleInstance *module_inst, uint32 tbl_idx)
|
||||
{
|
||||
/* careful, it might be a table in another module */
|
||||
WASMTableInstance *tbl_inst = module_inst->tables[tbl_idx];
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
if (tbl_inst->table_inst_linked) {
|
||||
tbl_inst = tbl_inst->table_inst_linked;
|
||||
if (tbl_idx < module_inst->module->import_table_count
|
||||
&& module_inst->e->table_insts_linked[tbl_idx]) {
|
||||
tbl_inst = module_inst->e->table_insts_linked[tbl_idx];
|
||||
}
|
||||
#endif
|
||||
bh_assert(tbl_inst);
|
||||
|
@ -495,6 +529,82 @@ const uint8 *
|
|||
wasm_loader_get_custom_section(WASMModule *module, const char *name,
|
||||
uint32 *len);
|
||||
|
||||
#if WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0 \
|
||||
|| WASM_ENABLE_WAMR_COMPILER != 0
|
||||
void
|
||||
jit_set_exception_with_id(WASMModuleInstance *module_inst, uint32 id);
|
||||
|
||||
/**
|
||||
* Check whether the app address and the buf is inside the linear memory,
|
||||
* and convert the app address into native address
|
||||
*/
|
||||
bool
|
||||
jit_check_app_addr_and_convert(WASMModuleInstance *module_inst, bool is_str,
|
||||
uint32 app_buf_addr, uint32 app_buf_size,
|
||||
void **p_native_addr);
|
||||
#endif /* end of WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0 \
|
||||
|| WASM_ENABLE_WAMR_COMPILER != 0 */
|
||||
|
||||
#if WASM_ENABLE_FAST_JIT != 0
|
||||
bool
|
||||
fast_jit_call_indirect(WASMExecEnv *exec_env, uint32 tbl_idx, uint32 elem_idx,
|
||||
uint32 type_idx, uint32 argc, uint32 *argv);
|
||||
|
||||
bool
|
||||
fast_jit_invoke_native(WASMExecEnv *exec_env, uint32 func_idx,
|
||||
struct WASMInterpFrame *prev_frame);
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0
|
||||
bool
|
||||
llvm_jit_call_indirect(WASMExecEnv *exec_env, uint32 tbl_idx, uint32 elem_idx,
|
||||
uint32 argc, uint32 *argv);
|
||||
|
||||
bool
|
||||
llvm_jit_invoke_native(WASMExecEnv *exec_env, uint32 func_idx, uint32 argc,
|
||||
uint32 *argv);
|
||||
|
||||
#if WASM_ENABLE_BULK_MEMORY != 0
|
||||
bool
|
||||
llvm_jit_memory_init(WASMModuleInstance *module_inst, uint32 seg_index,
|
||||
uint32 offset, uint32 len, uint32 dst);
|
||||
|
||||
bool
|
||||
llvm_jit_data_drop(WASMModuleInstance *module_inst, uint32 seg_index);
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_REF_TYPES != 0
|
||||
void
|
||||
llvm_jit_drop_table_seg(WASMModuleInstance *module_inst, uint32 tbl_seg_idx);
|
||||
|
||||
void
|
||||
llvm_jit_table_init(WASMModuleInstance *module_inst, uint32 tbl_idx,
|
||||
uint32 tbl_seg_idx, uint32 length, uint32 src_offset,
|
||||
uint32 dst_offset);
|
||||
|
||||
void
|
||||
llvm_jit_table_copy(WASMModuleInstance *module_inst, uint32 src_tbl_idx,
|
||||
uint32 dst_tbl_idx, uint32 length, uint32 src_offset,
|
||||
uint32 dst_offset);
|
||||
|
||||
void
|
||||
llvm_jit_table_fill(WASMModuleInstance *module_inst, uint32 tbl_idx,
|
||||
uint32 length, uint32 val, uint32 data_offset);
|
||||
|
||||
uint32
|
||||
llvm_jit_table_grow(WASMModuleInstance *module_inst, uint32 tbl_idx,
|
||||
uint32 inc_entries, uint32 init_val);
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_DUMP_CALL_STACK != 0 || WASM_ENABLE_PERF_PROFILING != 0
|
||||
bool
|
||||
llvm_jit_alloc_frame(WASMExecEnv *exec_env, uint32 func_index);
|
||||
|
||||
void
|
||||
llvm_jit_free_frame(WASMExecEnv *exec_env);
|
||||
#endif
|
||||
#endif /* end of WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0 */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -617,7 +617,7 @@ wasm_debug_instance_get_memregion(WASMDebugInstance *instance, uint64 addr)
|
|||
break;
|
||||
case WasmMemory:
|
||||
{
|
||||
memory = module_inst->default_memory;
|
||||
memory = wasm_get_default_memory(module_inst);
|
||||
|
||||
if (memory) {
|
||||
num_bytes_per_page = memory->num_bytes_per_page;
|
||||
|
@ -715,7 +715,7 @@ wasm_debug_instance_get_linear_mem(WASMDebugInstance *instance, uint64 offset,
|
|||
return false;
|
||||
|
||||
module_inst = (WASMModuleInstance *)exec_env->module_inst;
|
||||
memory = module_inst->default_memory;
|
||||
memory = wasm_get_default_memory(module_inst);
|
||||
if (memory) {
|
||||
num_bytes_per_page = memory->num_bytes_per_page;
|
||||
linear_mem_size = num_bytes_per_page * memory->cur_page_count;
|
||||
|
@ -748,7 +748,7 @@ wasm_debug_instance_set_linear_mem(WASMDebugInstance *instance, uint64 offset,
|
|||
return false;
|
||||
|
||||
module_inst = (WASMModuleInstance *)exec_env->module_inst;
|
||||
memory = module_inst->default_memory;
|
||||
memory = wasm_get_default_memory(module_inst);
|
||||
if (memory) {
|
||||
num_bytes_per_page = memory->num_bytes_per_page;
|
||||
linear_mem_size = num_bytes_per_page * memory->cur_page_count;
|
||||
|
@ -1134,10 +1134,10 @@ wasm_debug_instance_get_global(WASMDebugInstance *instance, int32 frame_index,
|
|||
|
||||
module_inst = (WASMModuleInstance *)exec_env->module_inst;
|
||||
global_data = module_inst->global_data;
|
||||
globals = module_inst->globals;
|
||||
globals = module_inst->e->globals;
|
||||
|
||||
if ((global_index < 0)
|
||||
|| ((uint32)global_index >= module_inst->global_count)) {
|
||||
|| ((uint32)global_index >= module_inst->e->global_count)) {
|
||||
return false;
|
||||
}
|
||||
global = globals + global_index;
|
||||
|
|
|
@ -23,7 +23,8 @@ set (WAMR_BUILD_PLATFORM "android")
|
|||
set (WAMR_BUILD_TARGET "X86_32")
|
||||
set (WAMR_BUILD_TYPE Release)
|
||||
set (WAMR_BUILD_INTERP 1)
|
||||
set (WAMR_BUILD_AOT 0)
|
||||
set (WAMR_BUILD_AOT 1)
|
||||
set (WAMR_BUILD_JIT 0)
|
||||
set (WAMR_BUILD_LIBC_BUILTIN 1)
|
||||
set (WAMR_BUILD_LIBC_WASI 1)
|
||||
|
||||
|
|
|
@ -125,6 +125,7 @@ set(MM_UTIL src/utils/multi_module_utils.c)
|
|||
set(EXAMPLES
|
||||
callback
|
||||
callback_chain
|
||||
clone
|
||||
empty_imports
|
||||
global
|
||||
hello
|
||||
|
@ -135,6 +136,12 @@ set(EXAMPLES
|
|||
trap
|
||||
)
|
||||
|
||||
if(WAMR_BUILD_JIT AND WAMR_BUILD_LAZY_JIT)
|
||||
if((${WAMR_BUILD_JIT} EQUAL 1) AND (${WAMR_BUILD_LAZY_JIT} EQUAL 1))
|
||||
list(APPEND EXAMPLES serialize)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
foreach(EX ${EXAMPLES})
|
||||
set(SRC ${CMAKE_CURRENT_LIST_DIR}/src/${EX}.c)
|
||||
|
||||
|
|
518
samples/wasm-c-api/src/clone.c
Normal file
518
samples/wasm-c-api/src/clone.c
Normal file
|
@ -0,0 +1,518 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "wasm_c_api.h"
|
||||
|
||||
#define WORKER_NUMBER 10
|
||||
|
||||
/******************************* VM *******************************/
|
||||
/* Use wasm_vm_t and vm_xxx to simulate a minimal Wasm VM in Envoy */
|
||||
|
||||
typedef struct _vm {
|
||||
wasm_engine_t *engine;
|
||||
wasm_store_t *store;
|
||||
wasm_module_t *module;
|
||||
wasm_instance_t *instance;
|
||||
wasm_func_t **function_list;
|
||||
wasm_memory_t *memory;
|
||||
wasm_table_t *table;
|
||||
wasm_extern_vec_t *exports;
|
||||
} wasm_vm_t;
|
||||
|
||||
typedef enum _clone_level {
|
||||
not_cloneable = 0,
|
||||
compiled_bytecode,
|
||||
instantiated_module
|
||||
} clone_level;
|
||||
|
||||
typedef struct _thread_arg_t {
|
||||
char name[32];
|
||||
bool *ready_go_flag;
|
||||
pthread_mutex_t *ready_go_lock;
|
||||
pthread_cond_t *ready_go_cond;
|
||||
const wasm_vm_t *base_vm;
|
||||
} thread_arg_t;
|
||||
|
||||
wasm_vm_t *
|
||||
vm_new()
|
||||
{
|
||||
wasm_vm_t *vm = NULL;
|
||||
|
||||
vm = malloc(sizeof(struct _vm));
|
||||
if (!vm)
|
||||
goto fail;
|
||||
|
||||
memset(vm, 0, sizeof(wasm_vm_t));
|
||||
|
||||
vm->engine = wasm_engine_new();
|
||||
if (!vm->engine)
|
||||
goto fail;
|
||||
|
||||
vm->store = wasm_store_new(vm->engine);
|
||||
if (!vm->store)
|
||||
goto fail;
|
||||
|
||||
return vm;
|
||||
|
||||
fail:
|
||||
if (vm) {
|
||||
if (vm->engine)
|
||||
wasm_engine_delete(vm->engine);
|
||||
|
||||
free(vm);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool
|
||||
vm_load(wasm_vm_t *vm, const wasm_byte_vec_t *binary)
|
||||
{
|
||||
vm->module = wasm_module_new(vm->store, binary);
|
||||
return vm->module != NULL;
|
||||
}
|
||||
|
||||
bool
|
||||
vm_link(wasm_vm_t *vm, wasm_extern_vec_t *imports)
|
||||
{
|
||||
vm->instance = wasm_instance_new(vm->store, vm->module, imports, NULL);
|
||||
if (!vm->instance)
|
||||
goto fail;
|
||||
|
||||
vm->exports = malloc(sizeof(wasm_extern_vec_t));
|
||||
if (!vm->exports)
|
||||
goto fail;
|
||||
|
||||
memset(vm->exports, 0, sizeof(wasm_extern_vec_t));
|
||||
wasm_instance_exports(vm->instance, vm->exports);
|
||||
/* an exported memory, and two exported functions */
|
||||
assert(vm->exports->size == 3);
|
||||
|
||||
/* bind memory */
|
||||
assert(wasm_extern_kind(vm->exports->data[0]) == WASM_EXTERN_MEMORY);
|
||||
vm->memory = wasm_extern_as_memory(vm->exports->data[0]);
|
||||
|
||||
vm->function_list = malloc(2 * sizeof(wasm_func_t *));
|
||||
if (!vm->function_list)
|
||||
goto fail;
|
||||
|
||||
memset(vm->function_list, 0, sizeof(2 * sizeof(wasm_func_t *)));
|
||||
|
||||
/* bind wasm_set_byte(...) */
|
||||
assert(wasm_extern_kind(vm->exports->data[1]) == WASM_EXTERN_FUNC);
|
||||
vm->function_list[0] = wasm_extern_as_func(vm->exports->data[1]);
|
||||
|
||||
/* bind wasm_get_byte(...) */
|
||||
assert(wasm_extern_kind(vm->exports->data[2]) == WASM_EXTERN_FUNC);
|
||||
vm->function_list[1] = wasm_extern_as_func(vm->exports->data[2]);
|
||||
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
wasm_vm_t *
|
||||
vm_clone_from_module(const wasm_vm_t *base)
|
||||
{
|
||||
printf("Initializing...\n");
|
||||
wasm_vm_t *secondary = NULL;
|
||||
|
||||
secondary = vm_new();
|
||||
if (secondary) {
|
||||
printf("Reuse module and bypass vm_load()...");
|
||||
secondary->module = base->module;
|
||||
}
|
||||
|
||||
return secondary;
|
||||
}
|
||||
|
||||
wasm_vm_t *
|
||||
vm_clone_from_instance(const wasm_vm_t *base)
|
||||
{
|
||||
/**
|
||||
* if do a clone of the level instantiated_module, need to malloc and
|
||||
* initialie
|
||||
* - global. WASMGlobalIntance and global data
|
||||
* - memory. WAAMMemoryInstance, memory_data and heap
|
||||
* - table. WASMTableInstance, table_data
|
||||
* - exports. all global, memory and table
|
||||
*
|
||||
* it is almost everything in wasm_instantiate() except funciton.
|
||||
*/
|
||||
(void)base;
|
||||
printf("Unsupported\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
wasm_vm_t *
|
||||
vm_clone(const wasm_vm_t *base, clone_level level)
|
||||
{
|
||||
if (level == not_cloneable)
|
||||
return NULL;
|
||||
|
||||
if (level == compiled_bytecode)
|
||||
return vm_clone_from_module(base);
|
||||
else
|
||||
return vm_clone_from_instance(base);
|
||||
}
|
||||
|
||||
wasm_vm_t *
|
||||
vm_release(wasm_vm_t *vm)
|
||||
{
|
||||
if (!vm)
|
||||
return NULL;
|
||||
|
||||
if (vm->function_list) {
|
||||
free(vm->function_list);
|
||||
vm->function_list = NULL;
|
||||
}
|
||||
|
||||
if (vm->exports) {
|
||||
wasm_extern_vec_delete(vm->exports);
|
||||
free(vm->exports);
|
||||
vm->exports = NULL;
|
||||
}
|
||||
|
||||
wasm_instance_delete(vm->instance);
|
||||
vm->instance = NULL;
|
||||
|
||||
wasm_module_delete(vm->module);
|
||||
vm->module = NULL;
|
||||
|
||||
wasm_store_delete(vm->store);
|
||||
vm->store = NULL;
|
||||
|
||||
wasm_engine_delete(vm->engine);
|
||||
vm->engine = NULL;
|
||||
|
||||
free(vm);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool
|
||||
vm_memory_set_byte(const wasm_vm_t *vm, uint32_t offset, uint8_t byte)
|
||||
{
|
||||
byte_t *data = wasm_memory_data(vm->memory);
|
||||
assert(data);
|
||||
*(data + offset) = byte;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
vm_memory_get_byte(const wasm_vm_t *vm, uint32_t offset, uint8_t *byte)
|
||||
{
|
||||
byte_t *data = wasm_memory_data(vm->memory);
|
||||
assert(data);
|
||||
*byte = *(data + offset);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
vm_function_set_byte(const wasm_vm_t *vm, uint32_t offset, uint8_t byte)
|
||||
{
|
||||
wasm_val_t a_v[2] = { WASM_I32_VAL(offset), WASM_I32_VAL(byte) };
|
||||
wasm_val_vec_t args = WASM_ARRAY_VEC(a_v);
|
||||
wasm_val_vec_t results = WASM_EMPTY_VEC;
|
||||
wasm_trap_t *trap = wasm_func_call(vm->function_list[0], &args, &results);
|
||||
if (trap)
|
||||
printf("call wasm_set_byte failed");
|
||||
|
||||
return trap != NULL;
|
||||
}
|
||||
|
||||
bool
|
||||
vm_function_get_byte(const wasm_vm_t *vm, uint32_t offset, uint8_t *byte)
|
||||
{
|
||||
wasm_val_t a_v[1] = { WASM_I32_VAL(offset) };
|
||||
wasm_val_vec_t args = WASM_ARRAY_VEC(a_v);
|
||||
wasm_val_t r_v[1] = { WASM_INIT_VAL };
|
||||
wasm_val_vec_t results = WASM_ARRAY_VEC(r_v);
|
||||
wasm_trap_t *trap = wasm_func_call(vm->function_list[1], &args, &results);
|
||||
if (trap) {
|
||||
printf("call wasm_get_byte failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
assert(results.data->kind == WASM_I32);
|
||||
*byte = results.data->of.i32;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
load_wasm_file_content(const char *file_name, wasm_byte_vec_t *out)
|
||||
{
|
||||
bool ret = false;
|
||||
#if WASM_ENABLE_AOT != 0 && WASM_ENABLE_INTERP == 0
|
||||
FILE *file = fopen(file_name, "rb");
|
||||
#else
|
||||
FILE *file = fopen(file_name, "rb");
|
||||
#endif
|
||||
if (!file) {
|
||||
printf("> Error loading .wasm!\n");
|
||||
goto quit;
|
||||
}
|
||||
|
||||
int offset = fseek(file, 0L, SEEK_END);
|
||||
if (offset == -1) {
|
||||
printf("> Error loading .wasm!\n");
|
||||
goto close_file;
|
||||
}
|
||||
|
||||
long file_size = ftell(file);
|
||||
if (file_size == -1) {
|
||||
printf("> Error loading .wasm!\n");
|
||||
goto close_file;
|
||||
}
|
||||
|
||||
offset = fseek(file, 0L, SEEK_SET);
|
||||
if (offset == -1) {
|
||||
printf("> Error loading .wasm!\n");
|
||||
goto close_file;
|
||||
}
|
||||
|
||||
wasm_byte_vec_new_uninitialized(out, file_size);
|
||||
if (fread(out->data, file_size, 1, file) != 1) {
|
||||
printf("> Error loading content!\n");
|
||||
goto close_file;
|
||||
}
|
||||
|
||||
ret = true;
|
||||
close_file:
|
||||
fclose(file);
|
||||
quit:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static pthread_key_t name_key;
|
||||
|
||||
wasm_trap_t *
|
||||
report_cb(const wasm_val_vec_t *args, wasm_val_vec_t *results)
|
||||
{
|
||||
(void)results;
|
||||
|
||||
assert(args->data[0].kind == WASM_I32);
|
||||
uint32_t chk_pnt_no = args->data[0].of.i32;
|
||||
|
||||
char *name = pthread_getspecific(name_key);
|
||||
printf("[%s] Pass CHK POINT #%u\n", name, chk_pnt_no);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool
|
||||
run_code_start(wasm_vm_t **out)
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
printf("Initializing...\n");
|
||||
wasm_vm_t *vm = vm_new();
|
||||
if (!vm)
|
||||
goto fail;
|
||||
|
||||
printf("Loading binary...\n");
|
||||
wasm_byte_vec_t binary = { 0 };
|
||||
#if WASM_ENABLE_AOT != 0 && WASM_ENABLE_INTERP == 0
|
||||
const char *file_name = "clone.aot";
|
||||
#else
|
||||
const char *file_name = "clone.wasm";
|
||||
#endif
|
||||
if (!load_wasm_file_content(file_name, &binary))
|
||||
goto release_vm;
|
||||
|
||||
printf("Compiling module...\n");
|
||||
ret = vm_load(vm, &binary);
|
||||
wasm_byte_vec_delete(&binary);
|
||||
if (!ret)
|
||||
goto release_vm;
|
||||
|
||||
printf("Creating callback...\n");
|
||||
wasm_functype_t *callback_type =
|
||||
wasm_functype_new_1_0(wasm_valtype_new_i32());
|
||||
if (!callback_type)
|
||||
goto release_vm;
|
||||
|
||||
wasm_func_t *callback = wasm_func_new(vm->store, callback_type, report_cb);
|
||||
wasm_functype_delete(callback_type);
|
||||
if (!callback)
|
||||
goto release_vm;
|
||||
|
||||
printf("Instantiating module...\n");
|
||||
wasm_extern_t *externs[] = { wasm_func_as_extern(callback) };
|
||||
wasm_extern_vec_t imports = WASM_ARRAY_VEC(externs);
|
||||
ret = vm_link(vm, &imports);
|
||||
wasm_func_delete(callback);
|
||||
if (!ret)
|
||||
goto release_vm;
|
||||
|
||||
*out = vm;
|
||||
return true;
|
||||
|
||||
release_vm:
|
||||
vm_release(vm);
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
run_warm_start_w_compiled_bytecode(const wasm_vm_t *first, wasm_vm_t **out)
|
||||
{
|
||||
bool ret;
|
||||
wasm_vm_t *secondary = vm_clone(first, compiled_bytecode);
|
||||
if (!secondary)
|
||||
goto fail;
|
||||
|
||||
printf("Creating callback...\n");
|
||||
wasm_functype_t *callback_type =
|
||||
wasm_functype_new_1_0(wasm_valtype_new_i32());
|
||||
if (!callback_type)
|
||||
goto release_vm;
|
||||
|
||||
wasm_func_t *callback =
|
||||
wasm_func_new(secondary->store, callback_type, report_cb);
|
||||
wasm_functype_delete(callback_type);
|
||||
if (!callback)
|
||||
goto release_vm;
|
||||
|
||||
printf("Instantiating module...\n");
|
||||
wasm_extern_t *externs[] = { wasm_func_as_extern(callback) };
|
||||
wasm_extern_vec_t imports = WASM_ARRAY_VEC(externs);
|
||||
ret = vm_link(secondary, &imports);
|
||||
wasm_func_delete(callback);
|
||||
if (!ret)
|
||||
goto release_vm;
|
||||
|
||||
*out = secondary;
|
||||
return true;
|
||||
|
||||
release_vm:
|
||||
vm_release(secondary);
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
run_warm_start_w_instantiated_module(const wasm_vm_t *first, wasm_vm_t **out)
|
||||
{
|
||||
wasm_vm_t *secondary = vm_clone(first, instantiated_module);
|
||||
if (!secondary)
|
||||
return false;
|
||||
|
||||
*out = secondary;
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
run_test(const wasm_vm_t *vm)
|
||||
{
|
||||
uint8_t byte = 0xFF;
|
||||
|
||||
/* read initialization */
|
||||
vm_function_get_byte(vm, 10, &byte);
|
||||
assert(byte == 0x0);
|
||||
vm_memory_get_byte(vm, 10, &byte);
|
||||
assert(byte == 0x0);
|
||||
|
||||
/* read after writing */
|
||||
vm_function_set_byte(vm, 16, 0xab);
|
||||
vm_function_get_byte(vm, 16, &byte);
|
||||
assert(byte == 0xab);
|
||||
|
||||
vm_memory_set_byte(vm, 16, 0xcd);
|
||||
vm_memory_get_byte(vm, 16, &byte);
|
||||
assert(byte == 0xcd);
|
||||
|
||||
/* reading and writing across */
|
||||
vm_function_set_byte(vm, 16, 0xef);
|
||||
vm_memory_get_byte(vm, 16, &byte);
|
||||
assert(byte == 0xef);
|
||||
|
||||
vm_memory_set_byte(vm, 16, 0x67);
|
||||
vm_function_get_byte(vm, 16, &byte);
|
||||
assert(byte == 0x67);
|
||||
|
||||
printf("All Passed ...\n");
|
||||
}
|
||||
|
||||
static void *
|
||||
thrd_func(void *arg)
|
||||
{
|
||||
thread_arg_t *thrd_arg = (thread_arg_t *)arg;
|
||||
printf("Running warm start at %s...\n", thrd_arg->name);
|
||||
|
||||
pthread_setspecific(name_key, thrd_arg->name);
|
||||
|
||||
wasm_vm_t *vm;
|
||||
if (!run_warm_start_w_compiled_bytecode(thrd_arg->base_vm, &vm))
|
||||
return NULL;
|
||||
|
||||
pthread_mutex_trylock(thrd_arg->ready_go_lock);
|
||||
while (!(*thrd_arg->ready_go_flag)) {
|
||||
pthread_cond_wait(thrd_arg->ready_go_cond, thrd_arg->ready_go_lock);
|
||||
}
|
||||
pthread_mutex_unlock(thrd_arg->ready_go_lock);
|
||||
|
||||
printf("Running test at %s...\n", thrd_arg->name);
|
||||
run_test(vm);
|
||||
|
||||
vm_release(vm);
|
||||
pthread_exit(NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
int ret = EXIT_FAILURE;
|
||||
bool ready_go_flag = false;
|
||||
pthread_mutex_t ready_go_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
pthread_cond_t ready_go_cond = PTHREAD_COND_INITIALIZER;
|
||||
pthread_key_create(&name_key, NULL);
|
||||
pthread_setspecific(name_key, "Execution Thread");
|
||||
|
||||
printf("Running cold start at the execution thread...\n");
|
||||
wasm_vm_t *base_vm;
|
||||
if (!run_code_start(&base_vm))
|
||||
goto quit;
|
||||
run_test(base_vm);
|
||||
|
||||
printf("Running warm start at other threads...\n");
|
||||
pthread_mutex_trylock(&ready_go_lock);
|
||||
|
||||
pthread_t tids[WORKER_NUMBER] = { 0 };
|
||||
thread_arg_t thrd_args[WORKER_NUMBER] = { 0 };
|
||||
for (size_t i = 0; i < sizeof(tids) / sizeof(tids[0]); i++) {
|
||||
thread_arg_t *thrd_arg = thrd_args + i;
|
||||
|
||||
snprintf(thrd_arg->name, 32, "Worker#%lu", i);
|
||||
thrd_arg->ready_go_cond = &ready_go_cond;
|
||||
thrd_arg->ready_go_lock = &ready_go_lock;
|
||||
thrd_arg->ready_go_flag = &ready_go_flag;
|
||||
thrd_arg->base_vm = base_vm;
|
||||
|
||||
int ret = pthread_create(&tids[i], NULL, thrd_func, thrd_arg);
|
||||
if (ret != 0)
|
||||
break;
|
||||
}
|
||||
|
||||
sleep(5);
|
||||
|
||||
ready_go_flag = true;
|
||||
pthread_mutex_unlock(&ready_go_lock);
|
||||
pthread_cond_broadcast(&ready_go_cond);
|
||||
|
||||
for (size_t i = 0; i < sizeof(tids) / sizeof(tids[0]); i++) {
|
||||
if (tids[i] != 0)
|
||||
pthread_join(tids[i], NULL);
|
||||
}
|
||||
vm_release(base_vm);
|
||||
ret = EXIT_SUCCESS;
|
||||
quit:
|
||||
return ret;
|
||||
}
|
15
samples/wasm-c-api/src/clone.wat
Normal file
15
samples/wasm-c-api/src/clone.wat
Normal file
|
@ -0,0 +1,15 @@
|
|||
(module
|
||||
(func $report (import "" "report") (param i32))
|
||||
|
||||
(memory (export "mem") 1 1)
|
||||
|
||||
(func $wasm_set_byte (export "set_byte") (param i32 i32)
|
||||
(call $report (i32.const 1))
|
||||
(i32.store8 (local.get 0) (local.get 1))
|
||||
)
|
||||
|
||||
(func $wasm_get_byte (export "get_byte") (param i32) (result i32)
|
||||
(call $report (i32.const 2))
|
||||
(i32.load(local.get 0))
|
||||
)
|
||||
)
|
129
samples/wasm-c-api/src/serialize.c
Normal file
129
samples/wasm-c-api/src/serialize.c
Normal file
|
@ -0,0 +1,129 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "wasm_c_api.h"
|
||||
|
||||
#define own
|
||||
|
||||
// A function to be called from Wasm code.
|
||||
own wasm_trap_t *
|
||||
hello_callback(const wasm_val_vec_t *args, wasm_val_vec_t *results)
|
||||
{
|
||||
printf("Calling back...\n");
|
||||
printf("> Hello World!\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, const char *argv[])
|
||||
{
|
||||
// Initialize.
|
||||
printf("Initializing...\n");
|
||||
wasm_engine_t *engine = wasm_engine_new();
|
||||
wasm_store_t *store = wasm_store_new(engine);
|
||||
|
||||
// Load binary.
|
||||
printf("Loading binary...\n");
|
||||
FILE *file = fopen("serialize.wasm", "rb");
|
||||
if (!file) {
|
||||
printf("> Error loading module!\n");
|
||||
return 1;
|
||||
}
|
||||
fseek(file, 0L, SEEK_END);
|
||||
size_t file_size = ftell(file);
|
||||
fseek(file, 0L, SEEK_SET);
|
||||
wasm_byte_vec_t binary;
|
||||
wasm_byte_vec_new_uninitialized(&binary, file_size);
|
||||
if (fread(binary.data, file_size, 1, file) != 1) {
|
||||
printf("> Error loading module!\n");
|
||||
return 1;
|
||||
}
|
||||
fclose(file);
|
||||
|
||||
// Compile.
|
||||
printf("Compiling module...\n");
|
||||
own wasm_module_t *module = wasm_module_new(store, &binary);
|
||||
if (!module) {
|
||||
printf("> Error compiling module!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
wasm_byte_vec_delete(&binary);
|
||||
|
||||
// Serialize module.
|
||||
printf("Serializing module...\n");
|
||||
own wasm_byte_vec_t serialized;
|
||||
wasm_module_serialize(module, &serialized);
|
||||
|
||||
wasm_module_delete(module);
|
||||
|
||||
// Deserialize module.
|
||||
printf("Deserializing module...\n");
|
||||
own wasm_module_t *deserialized =
|
||||
wasm_module_deserialize(store, &serialized);
|
||||
if (!deserialized) {
|
||||
printf("> Error deserializing module!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
wasm_byte_vec_delete(&serialized);
|
||||
|
||||
// Create external print functions.
|
||||
printf("Creating callback...\n");
|
||||
own wasm_functype_t *hello_type = wasm_functype_new_0_0();
|
||||
own wasm_func_t *hello_func =
|
||||
wasm_func_new(store, hello_type, hello_callback);
|
||||
|
||||
wasm_functype_delete(hello_type);
|
||||
|
||||
// Instantiate.
|
||||
printf("Instantiating deserialized module...\n");
|
||||
wasm_extern_t *externs[] = { wasm_func_as_extern(hello_func) };
|
||||
wasm_extern_vec_t imports = WASM_ARRAY_VEC(externs);
|
||||
own wasm_instance_t *instance =
|
||||
wasm_instance_new(store, deserialized, &imports, NULL);
|
||||
if (!instance) {
|
||||
printf("> Error instantiating module!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
wasm_func_delete(hello_func);
|
||||
|
||||
// Extract export.
|
||||
printf("Extracting export...\n");
|
||||
own wasm_extern_vec_t exports;
|
||||
wasm_instance_exports(instance, &exports);
|
||||
if (exports.size == 0) {
|
||||
printf("> Error accessing exports!\n");
|
||||
return 1;
|
||||
}
|
||||
const wasm_func_t *run_func = wasm_extern_as_func(exports.data[0]);
|
||||
if (run_func == NULL) {
|
||||
printf("> Error accessing export!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
wasm_module_delete(deserialized);
|
||||
wasm_instance_delete(instance);
|
||||
|
||||
// Call.
|
||||
printf("Calling export...\n");
|
||||
wasm_val_vec_t empty = WASM_EMPTY_VEC;
|
||||
if (wasm_func_call(run_func, &empty, &empty)) {
|
||||
printf("> Error calling function!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
wasm_extern_vec_delete(&exports);
|
||||
|
||||
// Shut down.
|
||||
printf("Shutting down...\n");
|
||||
wasm_store_delete(store);
|
||||
wasm_engine_delete(engine);
|
||||
|
||||
// All done.
|
||||
printf("Done.\n");
|
||||
return 0;
|
||||
}
|
4
samples/wasm-c-api/src/serialize.wat
Normal file
4
samples/wasm-c-api/src/serialize.wat
Normal file
|
@ -0,0 +1,4 @@
|
|||
(module
|
||||
(func $hello (import "" "hello"))
|
||||
(func (export "run") (call $hello))
|
||||
)
|
Loading…
Reference in New Issue
Block a user