mirror of
https://github.com/bytecodealliance/wasm-micro-runtime.git
synced 2024-11-26 15:32:05 +00:00
Refactor Orc JIT to enable lazy compilation (#974)
Refactor LLVM Orc JIT to actually enable the lazy compilation and speedup the launching process: https://llvm.org/docs/ORCv2.html#laziness Main modifications: - Create LLVM module for each wasm function, wrap it with thread safe module so that the modules can be compiled parallelly - Lookup function from aot module instance's func_ptrs but not directly call the function to decouple the module relationship - Compile the function when it is first called and hasn't been compiled - Create threads to pre-compile the WASM functions parallelly when loading - Set Lazy JIT as default, update document and build/test scripts
This commit is contained in:
parent
260d36a62d
commit
7636d86a76
|
@ -31,8 +31,8 @@ env:
|
|||
AOT_BUILD_OPTIONS: "-DWAMR_BUILD_AOT=1 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_INTERP=0 -DWAMR_BUILD_JIT=0 -DWAMR_BUILD_LAZY_JIT=0"
|
||||
CLASSIC_INTERP_BUILD_OPTIONS: "-DWAMR_BUILD_AOT=0 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_INTERP=1 -DWAMR_BUILD_JIT=0 -DWAMR_BUILD_LAZY_JIT=0"
|
||||
FAST_INTERP_BUILD_OPTIONS: "-DWAMR_BUILD_AOT=0 -DWAMR_BUILD_FAST_INTERP=1 -DWAMR_BUILD_INTERP=1 -DWAMR_BUILD_JIT=0 -DWAMR_BUILD_LAZY_JIT=0"
|
||||
JIT_BUILD_OPTIONS: "-DWAMR_BUILD_AOT=1 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_INTERP=0 -DWAMR_BUILD_JIT=1 -DWAMR_BUILD_LAZY_JIT=0"
|
||||
LAZY_JIT_BUILD_OPTIONS: "-DWAMR_BUILD_AOT=1 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_INTERP=0 -DWAMR_BUILD_JIT=1 -DWAMR_BUILD_LAZY_JIT=1"
|
||||
MC_JIT_BUILD_OPTIONS: "-DWAMR_BUILD_AOT=1 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_INTERP=0 -DWAMR_BUILD_JIT=1 -DWAMR_BUILD_LAZY_JIT=0"
|
||||
LLVM_CACHE_SUFFIX: "build-llvm_libraries_ex"
|
||||
|
||||
jobs:
|
||||
|
@ -193,8 +193,8 @@ jobs:
|
|||
# Running mode
|
||||
$CLASSIC_INTERP_BUILD_OPTIONS,
|
||||
$FAST_INTERP_BUILD_OPTIONS,
|
||||
$JIT_BUILD_OPTIONS,
|
||||
$LAZY_JIT_BUILD_OPTIONS,
|
||||
$MC_JIT_BUILD_OPTIONS,
|
||||
$AOT_BUILD_OPTIONS,
|
||||
]
|
||||
make_options_feature: [
|
||||
|
@ -232,11 +232,11 @@ jobs:
|
|||
make_options_feature: "-DWAMR_BUILD_DEBUG_AOT=1"
|
||||
# uncompatiable mode and feature
|
||||
# MULTI_MODULE only on INTERP mode
|
||||
- make_options_run_mode: $JIT_BUILD_OPTIONS
|
||||
- make_options_run_mode: $LAZY_JIT_BUILD_OPTIONS
|
||||
make_options_feature: "-DWAMR_BUILD_MULTI_MODULE=1"
|
||||
- make_options_run_mode: $AOT_BUILD_OPTIONS
|
||||
make_options_feature: "-DWAMR_BUILD_MULTI_MODULE=1"
|
||||
- make_options_run_mode: $LAZY_JIT_BUILD_OPTIONS
|
||||
- make_options_run_mode: $MC_JIT_BUILD_OPTIONS
|
||||
make_options_feature: "-DWAMR_BUILD_MULTI_MODULE=1"
|
||||
# SIMD only on JIT/AOT mode
|
||||
- make_options_run_mode: $CLASSIC_INTERP_BUILD_OPTIONS
|
||||
|
@ -246,10 +246,10 @@ jobs:
|
|||
# DEBUG_INTERP only on CLASSIC INTERP mode
|
||||
- make_options_run_mode: $AOT_BUILD_OPTIONS
|
||||
make_options_feature: "-DWAMR_BUILD_DEBUG_INTERP=1"
|
||||
- make_options_run_mode: $JIT_BUILD_OPTIONS
|
||||
make_options_feature: "-DWAMR_BUILD_DEBUG_INTERP=1"
|
||||
- make_options_run_mode: $LAZY_JIT_BUILD_OPTIONS
|
||||
make_options_feature: "-DWAMR_BUILD_DEBUG_INTERP=1"
|
||||
- make_options_run_mode: $MC_JIT_BUILD_OPTIONS
|
||||
make_options_feature: "-DWAMR_BUILD_DEBUG_INTERP=1"
|
||||
- make_options_run_mode: $FAST_INTERP_BUILD_OPTIONS
|
||||
make_options_feature: "-DWAMR_BUILD_DEBUG_INTERP=1"
|
||||
# DEBUG_AOT only on JIT/AOT mode
|
||||
|
@ -258,17 +258,17 @@ jobs:
|
|||
- make_options_run_mode: $FAST_INTERP_BUILD_OPTIONS
|
||||
make_options_feature: "-DWAMR_BUILD_DEBUG_AOT=1"
|
||||
# TODO: DEBUG_AOT on JIT
|
||||
- make_options_run_mode: $JIT_BUILD_OPTIONS
|
||||
make_options_feature: "-DWAMR_BUILD_DEBUG_AOT=1"
|
||||
- make_options_run_mode: $LAZY_JIT_BUILD_OPTIONS
|
||||
make_options_feature: "-DWAMR_BUILD_DEBUG_AOT=1"
|
||||
- make_options_run_mode: $MC_JIT_BUILD_OPTIONS
|
||||
make_options_feature: "-DWAMR_BUILD_DEBUG_AOT=1"
|
||||
# MINI_LOADER only on INTERP mode
|
||||
- make_options_run_mode: $AOT_BUILD_OPTIONS
|
||||
make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1"
|
||||
- make_options_run_mode: $JIT_BUILD_OPTIONS
|
||||
make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1"
|
||||
- make_options_run_mode: $LAZY_JIT_BUILD_OPTIONS
|
||||
make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1"
|
||||
- make_options_run_mode: $MC_JIT_BUILD_OPTIONS
|
||||
make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1"
|
||||
include:
|
||||
- os: ubuntu-18.04
|
||||
light: ${{ needs.check_repo.outputs.traffic_light_on_ubuntu_1804 }}
|
||||
|
@ -318,8 +318,8 @@ jobs:
|
|||
# Running mode
|
||||
$CLASSIC_INTERP_BUILD_OPTIONS,
|
||||
$FAST_INTERP_BUILD_OPTIONS,
|
||||
$JIT_BUILD_OPTIONS,
|
||||
$LAZY_JIT_BUILD_OPTIONS,
|
||||
$MC_JIT_BUILD_OPTIONS,
|
||||
$AOT_BUILD_OPTIONS,
|
||||
]
|
||||
os: [ubuntu-18.04, ubuntu-20.04, macos-latest]
|
||||
|
@ -339,11 +339,11 @@ jobs:
|
|||
exclude:
|
||||
# TODO: a .aot compatiable problem
|
||||
- os: macos-latest
|
||||
make_options: $JIT_BUILD_OPTIONS
|
||||
make_options: $LAZY_JIT_BUILD_OPTIONS
|
||||
- os: macos-latest
|
||||
make_options: $AOT_BUILD_OPTIONS
|
||||
- os: macos-latest
|
||||
make_options: $LAZY_JIT_BUILD_OPTIONS
|
||||
make_options: $MC_JIT_BUILD_OPTIONS
|
||||
steps:
|
||||
- name: light status
|
||||
run: echo "matrix.os=${{ matrix.os }}, light=${{ matrix.light }}"
|
||||
|
|
6
.github/workflows/compilation_on_sgx.yml
vendored
6
.github/workflows/compilation_on_sgx.yml
vendored
|
@ -31,8 +31,8 @@ env:
|
|||
AOT_BUILD_OPTIONS: "-DWAMR_BUILD_AOT=1 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_INTERP=0 -DWAMR_BUILD_JIT=0 -DWAMR_BUILD_LAZY_JIT=0"
|
||||
CLASSIC_INTERP_BUILD_OPTIONS: "-DWAMR_BUILD_AOT=0 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_INTERP=1 -DWAMR_BUILD_JIT=0 -DWAMR_BUILD_LAZY_JIT=0"
|
||||
FAST_INTERP_BUILD_OPTIONS: "-DWAMR_BUILD_AOT=0 -DWAMR_BUILD_FAST_INTERP=1 -DWAMR_BUILD_INTERP=1 -DWAMR_BUILD_JIT=0 -DWAMR_BUILD_LAZY_JIT=0"
|
||||
JIT_BUILD_OPTIONS: "-DWAMR_BUILD_AOT=1 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_INTERP=0 -DWAMR_BUILD_JIT=1 -DWAMR_BUILD_LAZY_JIT=0"
|
||||
LAZY_JIT_BUILD_OPTIONS: "-DWAMR_BUILD_AOT=1 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_INTERP=0 -DWAMR_BUILD_JIT=1 -DWAMR_BUILD_LAZY_JIT=1"
|
||||
MC_JIT_BUILD_OPTIONS: "-DWAMR_BUILD_AOT=1 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_INTERP=0 -DWAMR_BUILD_JIT=1 -DWAMR_BUILD_LAZY_JIT=0"
|
||||
LLVM_CACHE_SUFFIX: "build-llvm_libraries_ex"
|
||||
|
||||
jobs:
|
||||
|
@ -116,8 +116,8 @@ jobs:
|
|||
$CLASSIC_INTERP_BUILD_OPTIONS,
|
||||
$FAST_INTERP_BUILD_OPTIONS,
|
||||
# doesn't support
|
||||
# $JIT_BUILD_OPTIONS,
|
||||
# $LAZY_JIT_BUILD_OPTIONS,
|
||||
# $MC_JIT_BUILD_OPTIONS,
|
||||
$AOT_BUILD_OPTIONS,
|
||||
]
|
||||
make_options_feature: [
|
||||
|
@ -208,8 +208,8 @@ jobs:
|
|||
$CLASSIC_INTERP_BUILD_OPTIONS,
|
||||
$FAST_INTERP_BUILD_OPTIONS,
|
||||
# doesn't support
|
||||
#$JIT_BUILD_OPTIONS,
|
||||
#$LAZY_JIT_BUILD_OPTIONS,
|
||||
#$MC_JIT_BUILD_OPTIONS,
|
||||
#$AOT_BUILD_OPTIONS,
|
||||
]
|
||||
os: [ubuntu-20.04]
|
||||
|
|
|
@ -87,7 +87,9 @@ endif ()
|
|||
if (WAMR_BUILD_JIT EQUAL 1)
|
||||
if (WAMR_BUILD_AOT EQUAL 1)
|
||||
add_definitions("-DWASM_ENABLE_JIT=1")
|
||||
if (WAMR_BUILD_LAZY_JIT EQUAL 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)
|
||||
|
@ -128,11 +130,10 @@ else ()
|
|||
message (" WAMR AOT disabled")
|
||||
endif ()
|
||||
if (WAMR_BUILD_JIT EQUAL 1)
|
||||
message (" WAMR JIT enabled")
|
||||
if (WAMR_BUILD_LAZY_JIT EQUAL 1)
|
||||
message (" WAMR LazyJIT enabled")
|
||||
message (" WAMR Lazy JIT enabled")
|
||||
else ()
|
||||
message (" WAMR LazyJIT disabled")
|
||||
message (" WAMR MC JIT enabled")
|
||||
endif ()
|
||||
else ()
|
||||
message (" WAMR JIT disabled")
|
||||
|
|
|
@ -81,6 +81,10 @@
|
|||
#define WASM_ENABLE_LAZY_JIT 0
|
||||
#endif
|
||||
|
||||
#ifndef WASM_LAZY_JIT_COMPILE_THREAD_NUM
|
||||
#define WASM_LAZY_JIT_COMPILE_THREAD_NUM 4
|
||||
#endif
|
||||
|
||||
#if (WASM_ENABLE_AOT == 0) && (WASM_ENABLE_JIT != 0)
|
||||
/* LazyJIT or MCJIT can only be enabled when AOT is enabled */
|
||||
#undef WASM_ENABLE_JIT
|
||||
|
|
|
@ -2760,6 +2760,90 @@ aot_load_from_aot_file(const uint8 *buf, uint32 size, char *error_buf,
|
|||
}
|
||||
|
||||
#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)
|
||||
|
@ -2769,13 +2853,6 @@ aot_load_from_comp_data(AOTCompData *comp_data, AOTCompContext *comp_ctx,
|
|||
char func_name[32];
|
||||
AOTModule *module;
|
||||
|
||||
#if WASM_ENABLE_LAZY_JIT != 0
|
||||
LLVMOrcThreadSafeModuleRef ts_module;
|
||||
LLVMOrcJITDylibRef main_dylib;
|
||||
LLVMErrorRef error;
|
||||
LLVMOrcJITTargetAddress func_addr = 0;
|
||||
#endif
|
||||
|
||||
/* Allocate memory for module */
|
||||
if (!(module =
|
||||
loader_malloc(sizeof(AOTModule), error_buf, error_buf_size))) {
|
||||
|
@ -2839,44 +2916,28 @@ aot_load_from_comp_data(AOTCompData *comp_data, AOTCompContext *comp_ctx,
|
|||
}
|
||||
|
||||
#if WASM_ENABLE_LAZY_JIT != 0
|
||||
bh_assert(comp_ctx->lazy_orcjit);
|
||||
/* 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;
|
||||
|
||||
main_dylib = LLVMOrcLLLazyJITGetMainJITDylib(comp_ctx->lazy_orcjit);
|
||||
if (!main_dylib) {
|
||||
set_error_buf(error_buf, error_buf_size,
|
||||
"failed to get dynmaic library reference");
|
||||
goto fail3;
|
||||
}
|
||||
|
||||
ts_module = LLVMOrcCreateNewThreadSafeModule(comp_ctx->module,
|
||||
comp_ctx->ts_context);
|
||||
if (!ts_module) {
|
||||
set_error_buf(error_buf, error_buf_size,
|
||||
"failed to create thread safe module");
|
||||
goto fail3;
|
||||
}
|
||||
|
||||
if ((error = LLVMOrcLLLazyJITAddLLVMIRModule(comp_ctx->lazy_orcjit,
|
||||
main_dylib, ts_module))) {
|
||||
/*
|
||||
* If adding the ThreadSafeModule fails then we need to clean it up
|
||||
* ourselves. If adding it succeeds the JIT will manage the memory.
|
||||
*/
|
||||
aot_handle_llvm_errmsg(error_buf, error_buf_size,
|
||||
"failed to addIRModule: ", error);
|
||||
goto fail4;
|
||||
}
|
||||
|
||||
for (i = 0; i < comp_data->func_count; i++) {
|
||||
snprintf(func_name, sizeof(func_name), "%s%d", AOT_FUNC_PREFIX, i);
|
||||
if ((error = LLVMOrcLLLazyJITLookup(comp_ctx->lazy_orcjit, &func_addr,
|
||||
func_name))) {
|
||||
aot_handle_llvm_errmsg(error_buf, error_buf_size,
|
||||
"cannot lookup: ", error);
|
||||
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;
|
||||
}
|
||||
module->func_ptrs[i] = (void *)func_addr;
|
||||
func_addr = 0;
|
||||
}
|
||||
#else
|
||||
/* Resolve function addresses */
|
||||
|
@ -2897,7 +2958,7 @@ aot_load_from_comp_data(AOTCompData *comp_data, AOTCompContext *comp_ctx,
|
|||
if (size > 0
|
||||
&& !(module->func_type_indexes =
|
||||
loader_malloc(size, error_buf, error_buf_size))) {
|
||||
goto fail3;
|
||||
goto fail4;
|
||||
}
|
||||
for (i = 0; i < comp_data->func_count; i++)
|
||||
module->func_type_indexes[i] = comp_data->funcs[i]->func_type_index;
|
||||
|
@ -2911,6 +2972,29 @@ aot_load_from_comp_data(AOTCompData *comp_data, AOTCompContext *comp_ctx,
|
|||
< 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];
|
||||
|
@ -2945,10 +3029,16 @@ aot_load_from_comp_data(AOTCompData *comp_data, AOTCompContext *comp_ctx,
|
|||
return module;
|
||||
|
||||
#if WASM_ENABLE_LAZY_JIT != 0
|
||||
fail4:
|
||||
LLVMOrcDisposeThreadSafeModule(ts_module);
|
||||
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);
|
||||
|
@ -3034,6 +3124,10 @@ 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);
|
||||
|
||||
|
|
|
@ -1419,6 +1419,17 @@ aot_call_function(WASMExecEnv *exec_env, AOTFunctionInstance *function,
|
|||
}
|
||||
argc = func_type->param_cell_num;
|
||||
|
||||
#if WASM_ENABLE_LAZY_JIT != 0
|
||||
if (!function->u.func.func_ptr) {
|
||||
AOTModule *aot_module = (AOTModule *)module_inst->aot_module.ptr;
|
||||
if (!(function->u.func.func_ptr =
|
||||
aot_lookup_orcjit_func(aot_module->comp_ctx->orc_lazyjit,
|
||||
module_inst, function->func_index))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* set thread handle and stack boundary */
|
||||
wasm_exec_env_set_thread_info(exec_env);
|
||||
|
||||
|
@ -2300,6 +2311,15 @@ aot_call_indirect(WASMExecEnv *exec_env, uint32 tbl_idx, uint32 table_elem_idx,
|
|||
func_type_idx = func_type_indexes[func_idx];
|
||||
func_type = aot_module->func_types[func_type_idx];
|
||||
|
||||
#if WASM_ENABLE_LAZY_JIT != 0
|
||||
if (func_idx >= aot_module->import_func_count && !func_ptrs[func_idx]) {
|
||||
if (!(func_ptr = aot_lookup_orcjit_func(
|
||||
aot_module->comp_ctx->orc_lazyjit, module_inst, func_idx))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!(func_ptr = func_ptrs[func_idx])) {
|
||||
bh_assert(func_idx < aot_module->import_func_count);
|
||||
import_func = aot_module->import_funcs + func_idx;
|
||||
|
|
|
@ -232,7 +232,7 @@ WASM_DEFINE_VEC_OWN(store, wasm_store_delete)
|
|||
WASM_DEFINE_VEC_OWN(valtype, wasm_valtype_delete)
|
||||
|
||||
/* conflicting declaration between aot_export.h and aot.h */
|
||||
#if WASM_ENABLE_AOT != 0 && WASM_ENABLE_JIT != 0
|
||||
#if WASM_ENABLE_AOT != 0 && WASM_ENABLE_JIT != 0 && WASM_ENABLE_LAZY_JIT == 0
|
||||
bool
|
||||
aot_compile_wasm_file_init();
|
||||
|
||||
|
@ -266,7 +266,7 @@ wasm_engine_delete_internal(wasm_engine_t *engine)
|
|||
wasm_runtime_free(engine);
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_AOT != 0 && WASM_ENABLE_JIT != 0
|
||||
#if WASM_ENABLE_AOT != 0 && WASM_ENABLE_JIT != 0 && WASM_ENABLE_LAZY_JIT == 0
|
||||
aot_compile_wasm_file_destroy();
|
||||
#endif
|
||||
|
||||
|
@ -317,7 +317,7 @@ wasm_engine_new_internal(mem_alloc_type_t type, const MemAllocOption *opts)
|
|||
bh_log_set_verbose_level(3);
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_AOT != 0 && WASM_ENABLE_JIT != 0
|
||||
#if WASM_ENABLE_AOT != 0 && WASM_ENABLE_JIT != 0 && WASM_ENABLE_LAZY_JIT == 0
|
||||
if (!aot_compile_wasm_file_init()) {
|
||||
goto failed;
|
||||
}
|
||||
|
@ -1820,7 +1820,7 @@ wasm_module_new(wasm_store_t *store, const wasm_byte_vec_t *binary)
|
|||
char error_buf[128] = { 0 };
|
||||
wasm_module_ex_t *module_ex = NULL;
|
||||
PackageType pkg_type;
|
||||
#if WASM_ENABLE_AOT != 0 && WASM_ENABLE_JIT != 0
|
||||
#if WASM_ENABLE_AOT != 0 && WASM_ENABLE_JIT != 0 && WASM_ENABLE_LAZY_JIT == 0
|
||||
uint8 *aot_file_buf = NULL;
|
||||
uint32 aot_file_size;
|
||||
#endif
|
||||
|
@ -1858,7 +1858,7 @@ wasm_module_new(wasm_store_t *store, const wasm_byte_vec_t *binary)
|
|||
|
||||
INIT_VEC(module_ex->binary, wasm_byte_vec_new, binary->size, binary->data);
|
||||
|
||||
#if WASM_ENABLE_AOT != 0 && WASM_ENABLE_JIT != 0
|
||||
#if WASM_ENABLE_AOT != 0 && WASM_ENABLE_JIT != 0 && WASM_ENABLE_LAZY_JIT == 0
|
||||
if (Wasm_Module_Bytecode == pkg_type) {
|
||||
if (!(aot_file_buf = aot_compile_wasm_file(
|
||||
(uint8 *)module_ex->binary->data,
|
||||
|
|
|
@ -1307,7 +1307,7 @@ wasm_runtime_finalize_call_function(WASMExecEnv *exec_env,
|
|||
uint32 argv_i = 0, result_i = 0, ret_argv_i = 0;
|
||||
WASMType *func_type;
|
||||
|
||||
bh_assert(argv && ret_argv);
|
||||
bh_assert((argv && ret_argv) || (argc == 0));
|
||||
|
||||
if (argv == ret_argv) {
|
||||
return true;
|
||||
|
|
|
@ -2576,6 +2576,11 @@ aot_compile_wasm(AOTCompContext *comp_ctx)
|
|||
char *msg = NULL;
|
||||
bool ret;
|
||||
uint32 i;
|
||||
#if WASM_ENABLE_LAZY_JIT != 0
|
||||
LLVMErrorRef err;
|
||||
LLVMOrcJITDylibRef orc_main_dylib;
|
||||
LLVMOrcThreadSafeModuleRef orc_thread_safe_module;
|
||||
#endif
|
||||
|
||||
if (!aot_validate_wasm(comp_ctx)) {
|
||||
return false;
|
||||
|
@ -2607,6 +2612,7 @@ aot_compile_wasm(AOTCompContext *comp_ctx)
|
|||
|
||||
bh_print_time("Begin to verify LLVM module");
|
||||
|
||||
#if WASM_ENABLE_LAZY_JIT == 0
|
||||
ret = LLVMVerifyModule(comp_ctx->module, LLVMPrintMessageAction, &msg);
|
||||
if (!ret && msg) {
|
||||
if (msg[0] != '\0') {
|
||||
|
@ -2616,17 +2622,39 @@ aot_compile_wasm(AOTCompContext *comp_ctx)
|
|||
}
|
||||
LLVMDisposeMessage(msg);
|
||||
}
|
||||
#else
|
||||
for (i = 0; i < comp_ctx->func_ctx_count; i++) {
|
||||
ret = LLVMVerifyModule(comp_ctx->modules[i], LLVMPrintMessageAction,
|
||||
&msg);
|
||||
if (!ret && msg) {
|
||||
if (msg[0] != '\0') {
|
||||
aot_set_last_error(msg);
|
||||
LLVMDisposeMessage(msg);
|
||||
return false;
|
||||
}
|
||||
LLVMDisposeMessage(msg);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
bh_print_time("Begin to run function optimization passes");
|
||||
|
||||
/* Run function pass manager */
|
||||
if (comp_ctx->optimize) {
|
||||
#if WASM_ENABLE_LAZY_JIT == 0
|
||||
LLVMInitializeFunctionPassManager(comp_ctx->pass_mgr);
|
||||
for (i = 0; i < comp_ctx->func_ctx_count; i++)
|
||||
for (i = 0; i < comp_ctx->func_ctx_count; i++) {
|
||||
LLVMRunFunctionPassManager(comp_ctx->pass_mgr,
|
||||
comp_ctx->func_ctxes[i]->func);
|
||||
}
|
||||
#else
|
||||
for (i = 0; i < comp_ctx->func_ctx_count; i++) {
|
||||
LLVMRunPassManager(comp_ctx->pass_mgr, comp_ctx->modules[i]);
|
||||
}
|
||||
#endif /* end of WASM_ENABLE_LAZY_JIT */
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_LAZY_JIT == 0
|
||||
/* Run common pass manager */
|
||||
if (comp_ctx->optimize && !comp_ctx->is_jit_mode
|
||||
&& !comp_ctx->disable_llvm_lto) {
|
||||
|
@ -2656,6 +2684,7 @@ aot_compile_wasm(AOTCompContext *comp_ctx)
|
|||
LLVMDisposePassManager(common_pass_mgr);
|
||||
LLVMPassManagerBuilderDispose(pass_mgr_builder);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (comp_ctx->optimize && comp_ctx->is_indirect_mode) {
|
||||
LLVMPassManagerRef common_pass_mgr = NULL;
|
||||
|
@ -2673,14 +2702,58 @@ aot_compile_wasm(AOTCompContext *comp_ctx)
|
|||
if (aot_require_lower_switch_pass(comp_ctx))
|
||||
LLVMAddLowerSwitchPass(common_pass_mgr);
|
||||
|
||||
#if WASM_ENABLE_LAZY_JIT == 0
|
||||
LLVMRunPassManager(common_pass_mgr, comp_ctx->module);
|
||||
#else
|
||||
for (i = 0; i < comp_ctx->func_ctx_count; i++)
|
||||
LLVMRunPassManager(common_pass_mgr, comp_ctx->modules[i]);
|
||||
#endif
|
||||
|
||||
LLVMDisposePassManager(common_pass_mgr);
|
||||
}
|
||||
|
||||
#if 0
|
||||
#if WASM_ENABLE_LAZY_JIT == 0
|
||||
LLVMDumpModule(comp_ctx->module);
|
||||
#else
|
||||
for (i = 0; i < comp_ctx->func_ctx_count; i++) {
|
||||
LLVMDumpModule(comp_ctx->modules[i]);
|
||||
os_printf("\n");
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_LAZY_JIT != 0
|
||||
orc_main_dylib = LLVMOrcLLJITGetMainJITDylib(comp_ctx->orc_lazyjit);
|
||||
if (!orc_main_dylib) {
|
||||
aot_set_last_error("failed to get orc jit main dynmaic library");
|
||||
return false;
|
||||
}
|
||||
|
||||
for (i = 0; i < comp_ctx->func_ctx_count; i++) {
|
||||
orc_thread_safe_module = LLVMOrcCreateNewThreadSafeModule(
|
||||
comp_ctx->modules[i], comp_ctx->orc_thread_safe_context);
|
||||
if (!orc_thread_safe_module) {
|
||||
aot_set_last_error("failed to create thread safe module");
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((err = LLVMOrcLLJITAddLLVMIRModule(comp_ctx->orc_lazyjit,
|
||||
orc_main_dylib,
|
||||
orc_thread_safe_module))) {
|
||||
/* If adding the ThreadSafeModule fails then we need to clean it up
|
||||
by ourselves, otherwise the orc jit will manage the memory. */
|
||||
LLVMOrcDisposeThreadSafeModule(orc_thread_safe_module);
|
||||
aot_handle_llvm_errmsg("failed to addIRModule", err);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_LAZY_JIT == 0
|
||||
bool
|
||||
aot_emit_llvm_file(AOTCompContext *comp_ctx, const char *file_name)
|
||||
{
|
||||
|
@ -2928,3 +3001,4 @@ fail1:
|
|||
|
||||
return aot_file_buf;
|
||||
}
|
||||
#endif /* end of WASM_ENABLE_LAZY_JIT == 0 */
|
||||
|
|
|
@ -345,8 +345,8 @@ check_type_compatible(uint8 src_type, uint8 dst_type)
|
|||
else { \
|
||||
char *func_name = #name; \
|
||||
/* AOT mode, delcare the function */ \
|
||||
if (!(func = LLVMGetNamedFunction(comp_ctx->module, func_name)) \
|
||||
&& !(func = LLVMAddFunction(comp_ctx->module, func_name, \
|
||||
if (!(func = LLVMGetNamedFunction(func_ctx->module, func_name)) \
|
||||
&& !(func = LLVMAddFunction(func_ctx->module, func_name, \
|
||||
func_type))) { \
|
||||
aot_set_last_error("llvm add function failed."); \
|
||||
goto fail; \
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
#include "aot_compiler.h"
|
||||
#include "../aot/aot_runtime.h"
|
||||
|
||||
#if WASM_ENABLE_LAZY_JIT == 0
|
||||
|
||||
#define PUT_U64_TO_ADDR(addr, value) \
|
||||
do { \
|
||||
union { \
|
||||
|
@ -2804,3 +2806,5 @@ fail1:
|
|||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* end of WASM_ENABLE_JIT */
|
||||
|
|
|
@ -83,9 +83,9 @@ aot_emit_exception(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
}
|
||||
else {
|
||||
/* Create LLVM function with external function pointer */
|
||||
if (!(func = LLVMGetNamedFunction(comp_ctx->module,
|
||||
if (!(func = LLVMGetNamedFunction(func_ctx->module,
|
||||
"aot_set_exception_with_id"))
|
||||
&& !(func = LLVMAddFunction(comp_ctx->module,
|
||||
&& !(func = LLVMAddFunction(func_ctx->module,
|
||||
"aot_set_exception_with_id",
|
||||
func_type))) {
|
||||
aot_set_last_error("add LLVM function failed.");
|
||||
|
|
|
@ -184,9 +184,9 @@ call_aot_invoke_native_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
}
|
||||
}
|
||||
else {
|
||||
if (!(func = LLVMGetNamedFunction(comp_ctx->module, func_name))
|
||||
if (!(func = LLVMGetNamedFunction(func_ctx->module, func_name))
|
||||
&& !(func =
|
||||
LLVMAddFunction(comp_ctx->module, func_name, func_type))) {
|
||||
LLVMAddFunction(func_ctx->module, func_name, func_type))) {
|
||||
aot_set_last_error("add LLVM function failed.");
|
||||
return false;
|
||||
}
|
||||
|
@ -266,6 +266,130 @@ call_aot_invoke_native_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
return true;
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_LAZY_JIT != 0
|
||||
static bool
|
||||
lookup_orcjit_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
LLVMValueRef func_idx, LLVMValueRef *p_func)
|
||||
{
|
||||
LLVMBasicBlockRef block_curr, block_resolve_func, block_func_resolved;
|
||||
LLVMValueRef param_values[3], func, value, func_ptr, cmp, phi;
|
||||
LLVMTypeRef param_types[3], ret_type, func_type, func_ptr_type;
|
||||
|
||||
block_curr = LLVMGetInsertBlock(comp_ctx->builder);
|
||||
|
||||
if (!(block_resolve_func = LLVMAppendBasicBlockInContext(
|
||||
comp_ctx->context, func_ctx->func, "resolve_func"))) {
|
||||
aot_set_last_error("llvm add basic block failed.");
|
||||
return false;
|
||||
}
|
||||
if (!(block_func_resolved = LLVMAppendBasicBlockInContext(
|
||||
comp_ctx->context, func_ctx->func, "func_resolved"))) {
|
||||
aot_set_last_error("llvm add basic block failed.");
|
||||
return false;
|
||||
}
|
||||
LLVMMoveBasicBlockAfter(block_resolve_func, block_curr);
|
||||
LLVMMoveBasicBlockAfter(block_func_resolved, block_resolve_func);
|
||||
|
||||
LLVMPositionBuilderAtEnd(comp_ctx->builder, block_func_resolved);
|
||||
if (!(phi = LLVMBuildPhi(comp_ctx->builder, INT8_PTR_TYPE, "phi"))) {
|
||||
aot_set_last_error("llvm build phi failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
LLVMPositionBuilderAtEnd(comp_ctx->builder, block_curr);
|
||||
|
||||
/* Load function pointer */
|
||||
if (!(func_ptr =
|
||||
LLVMBuildInBoundsGEP(comp_ctx->builder, func_ctx->func_ptrs,
|
||||
&func_idx, 1, "func_ptr_tmp"))) {
|
||||
aot_set_last_error("llvm build inbounds gep failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(func = LLVMBuildLoad(comp_ctx->builder, func_ptr, "func_ptr"))) {
|
||||
aot_set_last_error("llvm build load failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* If func ptr is NULL, call aot_lookup_orcjit_func to resolve it */
|
||||
if (!(cmp = LLVMBuildIsNull(comp_ctx->builder, func, "cmp"))) {
|
||||
aot_set_last_error("llvm build is null failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Create condition br */
|
||||
if (!LLVMBuildCondBr(comp_ctx->builder, cmp, block_resolve_func,
|
||||
block_func_resolved)) {
|
||||
aot_set_last_error("llvm build cond br failed.");
|
||||
return false;
|
||||
}
|
||||
LLVMAddIncoming(phi, &func, &block_curr, 1);
|
||||
|
||||
LLVMPositionBuilderAtEnd(comp_ctx->builder, block_resolve_func);
|
||||
|
||||
param_types[0] = INT8_PTR_TYPE;
|
||||
param_types[1] = comp_ctx->aot_inst_type;
|
||||
param_types[2] = I32_TYPE;
|
||||
ret_type = INT8_PTR_TYPE;
|
||||
|
||||
if (!(func_type = LLVMFunctionType(ret_type, param_types, 3, false))
|
||||
|| !(func_ptr_type = LLVMPointerType(func_type, 0))) {
|
||||
aot_set_last_error("llvm add function type failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(value = I64_CONST((uint64)(uintptr_t)aot_lookup_orcjit_func))
|
||||
|| !(func = LLVMConstIntToPtr(value, func_ptr_type))) {
|
||||
aot_set_last_error("create LLVM value failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
param_values[0] = I64_CONST((uintptr_t)comp_ctx->orc_lazyjit);
|
||||
if (!param_values[0]) {
|
||||
aot_set_last_error("llvm build const failed.");
|
||||
return false;
|
||||
}
|
||||
if (!(param_values[0] =
|
||||
LLVMConstIntToPtr(param_values[0], INT8_PTR_TYPE))) {
|
||||
aot_set_last_error("llvm build bit cast failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
param_values[1] = func_ctx->aot_inst;
|
||||
|
||||
param_values[2] = func_idx;
|
||||
if (!param_values[2]) {
|
||||
aot_set_last_error("llvm build const failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Call the function */
|
||||
if (!(func = LLVMBuildCall(comp_ctx->builder, func, param_values, 3,
|
||||
"call_orcjit_lookup"))) {
|
||||
aot_set_last_error("LLVM build call failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Check whether exception was thrown when looking up func */
|
||||
if (!check_exception_thrown(comp_ctx, func_ctx)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
block_curr = LLVMGetInsertBlock(comp_ctx->builder);
|
||||
LLVMAddIncoming(phi, &func, &block_curr, 1);
|
||||
|
||||
if (!LLVMBuildBr(comp_ctx->builder, block_func_resolved)) {
|
||||
aot_set_last_error("llvm build br failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
LLVMPositionBuilderAtEnd(comp_ctx->builder, block_func_resolved);
|
||||
|
||||
*p_func = phi;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (WASM_ENABLE_DUMP_CALL_STACK != 0) || (WASM_ENABLE_PERF_PROFILING != 0)
|
||||
static bool
|
||||
call_aot_alloc_frame_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
||||
|
@ -579,8 +703,45 @@ aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
}
|
||||
}
|
||||
else {
|
||||
#if WASM_ENABLE_LAZY_JIT == 0
|
||||
func = func_ctxes[func_idx - import_func_count]->func;
|
||||
#else
|
||||
if (func_ctxes[func_idx - import_func_count] == func_ctx) {
|
||||
/* recursive call */
|
||||
func = func_ctx->func;
|
||||
}
|
||||
else {
|
||||
LLVMTypeRef func_ptr_type;
|
||||
LLVMValueRef func_idx_const = I32_CONST(func_idx);
|
||||
|
||||
if (!func_idx_const) {
|
||||
aot_set_last_error("llvm build const failed.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* For LAZY JIT, each function belongs to its own module,
|
||||
we call aot_lookup_orcjit_func to get the func pointer */
|
||||
if (!lookup_orcjit_func(comp_ctx, func_ctx, func_idx_const,
|
||||
&func)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(func_ptr_type = LLVMPointerType(
|
||||
func_ctxes[func_idx - import_func_count]->func_type,
|
||||
0))) {
|
||||
aot_set_last_error("construct func ptr type failed.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(func = LLVMBuildBitCast(comp_ctx->builder, func,
|
||||
func_ptr_type, "aot_func"))) {
|
||||
aot_set_last_error("llvm bit cast failed.");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
aot_func = func_ctxes[func_idx - import_func_count]->aot_func;
|
||||
callee_cell_num =
|
||||
aot_func->param_cell_num + aot_func->local_cell_num + 1;
|
||||
|
@ -704,9 +865,9 @@ call_aot_call_indirect_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
}
|
||||
}
|
||||
else {
|
||||
if (!(func = LLVMGetNamedFunction(comp_ctx->module, func_name))
|
||||
if (!(func = LLVMGetNamedFunction(func_ctx->module, func_name))
|
||||
&& !(func =
|
||||
LLVMAddFunction(comp_ctx->module, func_name, func_type))) {
|
||||
LLVMAddFunction(func_ctx->module, func_name, func_type))) {
|
||||
aot_set_last_error("add LLVM function failed.");
|
||||
return false;
|
||||
}
|
||||
|
@ -1197,6 +1358,7 @@ aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
+ 16))
|
||||
goto fail;
|
||||
|
||||
#if WASM_ENABLE_LAZY_JIT == 0
|
||||
/* Load function pointer */
|
||||
if (!(func_ptr =
|
||||
LLVMBuildInBoundsGEP(comp_ctx->builder, func_ctx->func_ptrs,
|
||||
|
@ -1209,6 +1371,12 @@ aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|||
aot_set_last_error("llvm build load failed.");
|
||||
goto fail;
|
||||
}
|
||||
#else
|
||||
/* For LAZY JIT, each function belongs to its own module,
|
||||
we call aot_lookup_orcjit_func to get the func pointer */
|
||||
if (!lookup_orcjit_func(comp_ctx, func_ctx, func_idx, &func_ptr))
|
||||
goto fail;
|
||||
#endif
|
||||
|
||||
if (!(llvm_func_type =
|
||||
LLVMFunctionType(ret_type, param_types, total_param_count, false))
|
||||
|
|
|
@ -709,9 +709,9 @@ aot_compile_op_memory_grow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
|
|||
else {
|
||||
char *func_name = "aot_enlarge_memory";
|
||||
/* AOT mode, delcare the function */
|
||||
if (!(func = LLVMGetNamedFunction(comp_ctx->module, func_name))
|
||||
if (!(func = LLVMGetNamedFunction(func_ctx->module, func_name))
|
||||
&& !(func =
|
||||
LLVMAddFunction(comp_ctx->module, func_name, func_type))) {
|
||||
LLVMAddFunction(func_ctx->module, func_name, func_type))) {
|
||||
aot_set_last_error("llvm add function failed.");
|
||||
return false;
|
||||
}
|
||||
|
@ -941,6 +941,7 @@ bool
|
|||
aot_compile_op_memory_copy(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
|
||||
{
|
||||
LLVMValueRef src, dst, src_addr, dst_addr, len, res;
|
||||
bool call_aot_memmove = false;
|
||||
|
||||
POP_I32(len);
|
||||
POP_I32(src);
|
||||
|
@ -952,29 +953,23 @@ aot_compile_op_memory_copy(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
|
|||
if (!(dst_addr = check_bulk_memory_overflow(comp_ctx, func_ctx, dst, len)))
|
||||
return false;
|
||||
|
||||
if (comp_ctx->is_indirect_mode) {
|
||||
#if WASM_ENABLE_LAZY_JIT != 0
|
||||
call_aot_memmove = true;
|
||||
#endif
|
||||
if (comp_ctx->is_indirect_mode)
|
||||
call_aot_memmove = true;
|
||||
|
||||
if (call_aot_memmove) {
|
||||
LLVMTypeRef param_types[3], ret_type, func_type, func_ptr_type;
|
||||
LLVMValueRef func, params[3];
|
||||
#if WASM_ENABLE_LAZY_JIT == 0
|
||||
int32 func_idx;
|
||||
#endif
|
||||
|
||||
if (!(dst_addr =
|
||||
LLVMBuildBitCast(comp_ctx->builder, dst_addr, INT32_PTR_TYPE,
|
||||
"memmove dst addr cast type"))) {
|
||||
aot_set_last_error("llvm cast memmove dst addr type failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(src_addr =
|
||||
LLVMBuildBitCast(comp_ctx->builder, src_addr, INT32_PTR_TYPE,
|
||||
"memmove src addr cast type"))) {
|
||||
aot_set_last_error("llvm cast memmove src addr type failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
param_types[0] = INT32_PTR_TYPE;
|
||||
param_types[1] = INT32_PTR_TYPE;
|
||||
param_types[0] = INT8_PTR_TYPE;
|
||||
param_types[1] = INT8_PTR_TYPE;
|
||||
param_types[2] = I32_TYPE;
|
||||
ret_type = INT32_PTR_TYPE;
|
||||
ret_type = INT8_PTR_TYPE;
|
||||
|
||||
if (!(func_type = LLVMFunctionType(ret_type, param_types, 3, false))) {
|
||||
aot_set_last_error("create LLVM function type failed.");
|
||||
|
@ -986,6 +981,7 @@ aot_compile_op_memory_copy(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
|
|||
return false;
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_LAZY_JIT == 0
|
||||
func_idx = aot_get_native_symbol_index(comp_ctx, "memmove");
|
||||
if (func_idx < 0) {
|
||||
return false;
|
||||
|
@ -994,12 +990,19 @@ aot_compile_op_memory_copy(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
|
|||
func_ptr_type, func_idx))) {
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
if (!(func = I64_CONST((uint64)(uintptr_t)aot_memmove))
|
||||
|| !(func = LLVMConstIntToPtr(func, func_ptr_type))) {
|
||||
aot_set_last_error("create LLVM value failed.");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
params[0] = dst_addr;
|
||||
params[1] = src_addr;
|
||||
params[2] = len;
|
||||
if (!(res = LLVMBuildCall(comp_ctx->builder, func, params, 3,
|
||||
"call memmove"))) {
|
||||
"call_memmove"))) {
|
||||
aot_set_last_error("llvm build memmove failed.");
|
||||
return false;
|
||||
}
|
||||
|
@ -1021,6 +1024,8 @@ bool
|
|||
aot_compile_op_memory_fill(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
|
||||
{
|
||||
LLVMValueRef val, dst, dst_addr, len, res;
|
||||
LLVMTypeRef param_types[3], ret_type, func_type, func_ptr_type;
|
||||
LLVMValueRef func, params[3];
|
||||
|
||||
POP_I32(len);
|
||||
POP_I32(val);
|
||||
|
@ -1029,64 +1034,57 @@ aot_compile_op_memory_fill(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
|
|||
if (!(dst_addr = check_bulk_memory_overflow(comp_ctx, func_ctx, dst, len)))
|
||||
return false;
|
||||
|
||||
if (!(val = LLVMBuildIntCast2(comp_ctx->builder, val, INT8_TYPE, true,
|
||||
"mem_set_value"))) {
|
||||
aot_set_last_error("llvm build int cast2 failed.");
|
||||
param_types[0] = INT8_PTR_TYPE;
|
||||
param_types[1] = I32_TYPE;
|
||||
param_types[2] = I32_TYPE;
|
||||
ret_type = INT8_PTR_TYPE;
|
||||
|
||||
if (!(func_type = LLVMFunctionType(ret_type, param_types, 3, false))) {
|
||||
aot_set_last_error("create LLVM function type failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (comp_ctx->is_indirect_mode) {
|
||||
LLVMTypeRef param_types[3], ret_type, func_type, func_ptr_type;
|
||||
LLVMValueRef func, params[3];
|
||||
int32 func_idx;
|
||||
if (!(func_ptr_type = LLVMPointerType(func_type, 0))) {
|
||||
aot_set_last_error("create LLVM function pointer type failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(dst_addr =
|
||||
LLVMBuildBitCast(comp_ctx->builder, dst_addr, INT32_PTR_TYPE,
|
||||
"memset dst addr cast type"))) {
|
||||
aot_set_last_error("llvm cast memset dst addr type failed.");
|
||||
if (comp_ctx->is_jit_mode) {
|
||||
if (!(func = I64_CONST((uint64)(uintptr_t)aot_memset))
|
||||
|| !(func = LLVMConstIntToPtr(func, func_ptr_type))) {
|
||||
aot_set_last_error("create LLVM value failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
param_types[0] = INT32_PTR_TYPE;
|
||||
param_types[1] = INT8_TYPE;
|
||||
param_types[2] = I32_TYPE;
|
||||
ret_type = INT32_PTR_TYPE;
|
||||
|
||||
if (!(func_type = LLVMFunctionType(ret_type, param_types, 3, false))) {
|
||||
aot_set_last_error("create LLVM function type failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(func_ptr_type = LLVMPointerType(func_type, 0))) {
|
||||
aot_set_last_error("create LLVM function pointer type failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
func_idx = aot_get_native_symbol_index(comp_ctx, "memset");
|
||||
if (func_idx < 0) {
|
||||
}
|
||||
else if (comp_ctx->is_indirect_mode) {
|
||||
int32 func_index;
|
||||
func_index = aot_get_native_symbol_index(comp_ctx, "memset");
|
||||
if (func_index < 0) {
|
||||
return false;
|
||||
}
|
||||
if (!(func = aot_get_func_from_table(comp_ctx, func_ctx->native_symbol,
|
||||
func_ptr_type, func_idx))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
params[0] = dst_addr;
|
||||
params[1] = val;
|
||||
params[2] = len;
|
||||
if (!(res = LLVMBuildCall(comp_ctx->builder, func, params, 3,
|
||||
"call memset"))) {
|
||||
aot_set_last_error("llvm build memset failed.");
|
||||
func_ptr_type, func_index))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!(res =
|
||||
LLVMBuildMemSet(comp_ctx->builder, dst_addr, val, len, 1))) {
|
||||
aot_set_last_error("llvm build memset failed.");
|
||||
if (!(func = LLVMGetNamedFunction(func_ctx->module, "memset"))
|
||||
&& !(func =
|
||||
LLVMAddFunction(func_ctx->module, "memset", func_type))) {
|
||||
aot_set_last_error("llvm add function failed.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
params[0] = dst_addr;
|
||||
params[1] = val;
|
||||
params[2] = len;
|
||||
if (!(res = LLVMBuildCall(comp_ctx->builder, func, params, 3,
|
||||
"call_memset"))) {
|
||||
aot_set_last_error("llvm build memset failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
|
|
|
@ -41,8 +41,9 @@ wasm_type_to_llvm_type(AOTLLVMTypes *llvm_types, uint8 wasm_type)
|
|||
* Add LLVM function
|
||||
*/
|
||||
static LLVMValueRef
|
||||
aot_add_llvm_func(AOTCompContext *comp_ctx, AOTFuncType *aot_func_type,
|
||||
uint32 func_index, LLVMTypeRef *p_func_type)
|
||||
aot_add_llvm_func(AOTCompContext *comp_ctx, LLVMModuleRef module,
|
||||
AOTFuncType *aot_func_type, uint32 func_index,
|
||||
LLVMTypeRef *p_func_type)
|
||||
{
|
||||
LLVMValueRef func = NULL;
|
||||
LLVMTypeRef *param_types, ret_type, func_type;
|
||||
|
@ -97,7 +98,7 @@ aot_add_llvm_func(AOTCompContext *comp_ctx, AOTFuncType *aot_func_type,
|
|||
|
||||
/* Add LLVM function */
|
||||
snprintf(func_name, sizeof(func_name), "%s%d", AOT_FUNC_PREFIX, func_index);
|
||||
if (!(func = LLVMAddFunction(comp_ctx->module, func_name, func_type))) {
|
||||
if (!(func = LLVMAddFunction(module, func_name, func_type))) {
|
||||
aot_set_last_error("add LLVM function failed.");
|
||||
goto fail;
|
||||
}
|
||||
|
@ -616,9 +617,16 @@ aot_create_func_context(AOTCompData *comp_data, AOTCompContext *comp_ctx,
|
|||
memset(func_ctx, 0, (uint32)size);
|
||||
func_ctx->aot_func = func;
|
||||
|
||||
#if WASM_ENABLE_LAZY_JIT == 0
|
||||
func_ctx->module = comp_ctx->module;
|
||||
#else
|
||||
func_ctx->module = comp_ctx->modules[func_index];
|
||||
#endif
|
||||
|
||||
/* Add LLVM function */
|
||||
if (!(func_ctx->func = aot_add_llvm_func(comp_ctx, aot_func_type,
|
||||
func_index, &func_ctx->func_type)))
|
||||
if (!(func_ctx->func =
|
||||
aot_add_llvm_func(comp_ctx, func_ctx->module, aot_func_type,
|
||||
func_index, &func_ctx->func_type)))
|
||||
goto fail;
|
||||
|
||||
/* Create function's first AOTBlock */
|
||||
|
@ -1214,152 +1222,211 @@ LLVMAddPromoteMemoryToRegisterPass(LLVMPassManagerRef PM);
|
|||
|
||||
#if WASM_ENABLE_LAZY_JIT != 0
|
||||
void
|
||||
aot_handle_llvm_errmsg(char *error_buf, uint32 error_buf_size,
|
||||
const char *string, LLVMErrorRef error)
|
||||
aot_handle_llvm_errmsg(const char *string, LLVMErrorRef err)
|
||||
{
|
||||
char *err_msg = LLVMGetErrorMessage(error);
|
||||
if (error_buf != NULL) {
|
||||
snprintf(error_buf, error_buf_size, "%s: %s", string, err_msg);
|
||||
}
|
||||
char *err_msg = LLVMGetErrorMessage(err);
|
||||
aot_set_last_error_v("%s: %s", string, err_msg);
|
||||
LLVMDisposeErrorMessage(err_msg);
|
||||
}
|
||||
|
||||
static bool
|
||||
llvm_orcjit_create(AOTCompContext *comp_ctx)
|
||||
orc_lazyjit_create(AOTCompContext *comp_ctx, uint32 func_count)
|
||||
{
|
||||
uint32 i;
|
||||
char *err_msg = NULL;
|
||||
char *cpu = NULL;
|
||||
char *features = NULL;
|
||||
char *llvm_triple = NULL;
|
||||
char buf[128] = { 0 };
|
||||
|
||||
LLVMErrorRef error;
|
||||
char func_name[32] = { 0 };
|
||||
LLVMErrorRef err;
|
||||
LLVMTargetRef llvm_targetref = NULL;
|
||||
LLVMTargetMachineRef tm_opt = NULL;
|
||||
LLVMTargetMachineRef tm_opt2 = NULL;
|
||||
LLVMOrcLLLazyJITRef lazy_orcjit = NULL;
|
||||
LLVMOrcJITTargetMachineBuilderRef tm_builder = NULL;
|
||||
LLVMOrcLLLazyJITBuilderRef lazy_orcjit_builder = NULL;
|
||||
#if LLVM_VERSION_MAJOR < 12
|
||||
LLVMOrcJITDylibDefinitionGeneratorRef main_gen = NULL;
|
||||
#else
|
||||
LLVMOrcDefinitionGeneratorRef main_gen = NULL;
|
||||
#endif
|
||||
LLVMTargetMachineRef target_machine_for_orcjit = NULL;
|
||||
LLVMOrcLLJITRef orc_lazyjit = NULL;
|
||||
LLVMOrcJITTargetMachineBuilderRef target_machine_builder = NULL;
|
||||
LLVMOrcLLJITBuilderRef orc_lazyjit_builder = NULL;
|
||||
LLVMOrcMaterializationUnitRef orc_material_unit = NULL;
|
||||
LLVMOrcExecutionSessionRef orc_execution_session = NULL;
|
||||
LLVMOrcLazyCallThroughManagerRef orc_call_through_mgr = NULL;
|
||||
LLVMOrcIndirectStubsManagerRef orc_indirect_stub_mgr = NULL;
|
||||
LLVMOrcCSymbolAliasMapPair *orc_symbol_map_pairs = NULL;
|
||||
|
||||
llvm_triple = LLVMGetDefaultTargetTriple();
|
||||
if (llvm_triple == NULL) {
|
||||
snprintf(buf, sizeof(buf), "failed to get default target triple.");
|
||||
aot_set_last_error("failed to get default target triple.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (LLVMGetTargetFromTriple(llvm_triple, &llvm_targetref, &err_msg) != 0) {
|
||||
snprintf(buf, sizeof(buf),
|
||||
"failed to get target reference from triple %s.", err_msg);
|
||||
aot_set_last_error_v("failed to get llvm target from triple %s.",
|
||||
err_msg);
|
||||
LLVMDisposeMessage(err_msg);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!LLVMTargetHasJIT(llvm_targetref)) {
|
||||
snprintf(buf, sizeof(buf), "unspported JIT on this platform.");
|
||||
aot_set_last_error("unspported JIT on this platform.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
cpu = LLVMGetHostCPUName();
|
||||
if (cpu == NULL) {
|
||||
snprintf(buf, sizeof(buf), "failed to get host cpu information.");
|
||||
aot_set_last_error("failed to get host cpu information.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
features = LLVMGetHostCPUFeatures();
|
||||
if (features == NULL) {
|
||||
snprintf(buf, sizeof(buf), "failed to get host cpu features.");
|
||||
aot_set_last_error("failed to get host cpu features.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
LOG_VERBOSE("LLVM ORCJIT detected CPU \"%s\", with features \"%s\"\n", cpu,
|
||||
features);
|
||||
|
||||
tm_opt = LLVMCreateTargetMachine(llvm_targetref, llvm_triple, cpu, features,
|
||||
LLVMCodeGenLevelAggressive,
|
||||
LLVMRelocDefault, LLVMCodeModelJITDefault);
|
||||
if (!tm_opt) {
|
||||
snprintf(buf, sizeof(buf), "failed to create target machine.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
tm_opt2 = LLVMCreateTargetMachine(
|
||||
llvm_targetref, llvm_triple, cpu, features, LLVMCodeGenLevelAggressive,
|
||||
comp_ctx->target_machine = LLVMCreateTargetMachine(
|
||||
llvm_targetref, llvm_triple, cpu, features, LLVMCodeGenLevelDefault,
|
||||
LLVMRelocDefault, LLVMCodeModelJITDefault);
|
||||
if (!tm_opt2) {
|
||||
snprintf(buf, sizeof(buf), "failed to create target machine2.");
|
||||
if (!comp_ctx->target_machine) {
|
||||
aot_set_last_error("failed to create target machine.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* if success, it will dispose tm_opt2 memory. */
|
||||
tm_builder = LLVMOrcJITTargetMachineBuilderCreateFromTargetMachine(tm_opt2);
|
||||
if (!tm_builder) {
|
||||
snprintf(buf, sizeof(buf), "failed to create target machine builder.");
|
||||
goto fail;
|
||||
}
|
||||
tm_opt2 = NULL;
|
||||
|
||||
lazy_orcjit_builder = LLVMOrcCreateLLLazyJITBuilder();
|
||||
if (!lazy_orcjit_builder) {
|
||||
snprintf(buf, sizeof(buf), "failed to create lazy jit builder.");
|
||||
target_machine_for_orcjit = LLVMCreateTargetMachine(
|
||||
llvm_targetref, llvm_triple, cpu, features, LLVMCodeGenLevelDefault,
|
||||
LLVMRelocDefault, LLVMCodeModelJITDefault);
|
||||
if (!target_machine_for_orcjit) {
|
||||
aot_set_last_error("failed to create target machine.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
LLVMOrcLLLazyJITBuilderSetJITTargetMachineBuilder(lazy_orcjit_builder,
|
||||
tm_builder);
|
||||
|
||||
/* if success, it will dispose lazy_orcjit_builder memory */
|
||||
error = LLVMOrcCreateLLLazyJIT(&lazy_orcjit, lazy_orcjit_builder);
|
||||
if (error) {
|
||||
aot_handle_llvm_errmsg(buf, sizeof(buf),
|
||||
"failed to create llvm lazy orcjit instance",
|
||||
error);
|
||||
target_machine_builder =
|
||||
LLVMOrcJITTargetMachineBuilderCreateFromTargetMachine(
|
||||
target_machine_for_orcjit);
|
||||
if (!target_machine_builder) {
|
||||
aot_set_last_error("failed to create target machine builder.");
|
||||
goto fail;
|
||||
}
|
||||
lazy_orcjit_builder = NULL;
|
||||
/* The target_machine_for_orcjit has been disposed before
|
||||
LLVMOrcJITTargetMachineBuilderCreateFromTargetMachine() returns */
|
||||
target_machine_for_orcjit = NULL;
|
||||
|
||||
error = LLVMOrcCreateDynamicLibrarySearchGeneratorForProcess(
|
||||
&main_gen, LLVMOrcLLLazyJITGetGlobalPrefix(lazy_orcjit), 0, NULL);
|
||||
if (error) {
|
||||
aot_handle_llvm_errmsg(
|
||||
buf, sizeof(buf),
|
||||
"failed to create dynmaic library search generator", error);
|
||||
orc_lazyjit_builder = LLVMOrcCreateLLJITBuilder();
|
||||
if (!orc_lazyjit_builder) {
|
||||
aot_set_last_error("failed to create lazy jit builder.");
|
||||
goto fail;
|
||||
}
|
||||
LLVMOrcLLJITBuilderSetNumCompileThreads(orc_lazyjit_builder,
|
||||
WASM_LAZY_JIT_COMPILE_THREAD_NUM);
|
||||
LLVMOrcLLJITBuilderSetJITTargetMachineBuilder(orc_lazyjit_builder,
|
||||
target_machine_builder);
|
||||
/* Should not dispose of the JITTargetMachineBuilder after calling
|
||||
LLVMOrcLLJITBuilderSetJITTargetMachineBuilder() */
|
||||
target_machine_builder = NULL;
|
||||
|
||||
LLVMOrcJITDylibAddGenerator(LLVMOrcLLLazyJITGetMainJITDylib(lazy_orcjit),
|
||||
main_gen);
|
||||
err = LLVMOrcCreateLLJIT(&orc_lazyjit, orc_lazyjit_builder);
|
||||
if (err) {
|
||||
aot_handle_llvm_errmsg("failed to create llvm lazy orcjit instance",
|
||||
err);
|
||||
goto fail;
|
||||
}
|
||||
/* The orc_lazyjit_builder is managed by orc_lazyjit after calling
|
||||
LLVMOrcCreateLLJIT(), here we should not dispose it again */
|
||||
orc_lazyjit_builder = NULL;
|
||||
|
||||
if (func_count > 0) {
|
||||
orc_execution_session = LLVMOrcLLJITGetExecutionSession(orc_lazyjit);
|
||||
if (!orc_execution_session) {
|
||||
aot_set_last_error("failed to get orc execution session");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
err = LLVMOrcCreateLocalLazyCallThroughManager(
|
||||
llvm_triple, orc_execution_session, 0, &orc_call_through_mgr);
|
||||
if (err) {
|
||||
aot_handle_llvm_errmsg("failed to create orc call through manager",
|
||||
err);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
orc_indirect_stub_mgr =
|
||||
LLVMOrcCreateLocalIndirectStubsManager(llvm_triple);
|
||||
if (!orc_indirect_stub_mgr) {
|
||||
aot_set_last_error("failed to create orc indirect stub manager");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(orc_symbol_map_pairs = wasm_runtime_malloc(
|
||||
sizeof(LLVMOrcCSymbolAliasMapPair) * func_count))) {
|
||||
aot_set_last_error("failed to allocate memory");
|
||||
goto fail;
|
||||
}
|
||||
memset(orc_symbol_map_pairs, 0,
|
||||
sizeof(LLVMOrcCSymbolAliasMapPair) * func_count);
|
||||
|
||||
for (i = 0; i < func_count; i++) {
|
||||
snprintf(func_name, sizeof(func_name), "orcjit_%s%d",
|
||||
AOT_FUNC_PREFIX, i);
|
||||
orc_symbol_map_pairs[i].Name =
|
||||
LLVMOrcExecutionSessionIntern(orc_execution_session, func_name);
|
||||
snprintf(func_name, sizeof(func_name), "%s%d", AOT_FUNC_PREFIX, i);
|
||||
orc_symbol_map_pairs[i].Entry.Name =
|
||||
LLVMOrcExecutionSessionIntern(orc_execution_session, func_name);
|
||||
orc_symbol_map_pairs[i].Entry.Flags.GenericFlags =
|
||||
LLVMJITSymbolGenericFlagsExported
|
||||
| LLVMJITSymbolGenericFlagsCallable;
|
||||
orc_symbol_map_pairs[i].Entry.Flags.TargetFlags =
|
||||
LLVMJITSymbolGenericFlagsExported
|
||||
| LLVMJITSymbolGenericFlagsCallable;
|
||||
|
||||
if (!orc_symbol_map_pairs[i].Name
|
||||
|| !orc_symbol_map_pairs[i].Entry.Name) {
|
||||
aot_set_last_error("failed to allocate memory");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
orc_material_unit =
|
||||
LLVMOrcLazyReexports(orc_call_through_mgr, orc_indirect_stub_mgr,
|
||||
LLVMOrcLLJITGetMainJITDylib(orc_lazyjit),
|
||||
orc_symbol_map_pairs, func_count);
|
||||
if (!orc_material_unit) {
|
||||
aot_set_last_error("failed to orc re-exports");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
comp_ctx->orc_lazyjit = orc_lazyjit;
|
||||
comp_ctx->orc_material_unit = orc_material_unit;
|
||||
comp_ctx->orc_symbol_map_pairs = orc_symbol_map_pairs;
|
||||
comp_ctx->orc_call_through_mgr = orc_call_through_mgr;
|
||||
comp_ctx->orc_indirect_stub_mgr = orc_indirect_stub_mgr;
|
||||
|
||||
comp_ctx->lazy_orcjit = lazy_orcjit;
|
||||
comp_ctx->target_machine = tm_opt;
|
||||
comp_ctx->tm_builder = tm_builder;
|
||||
LLVMDisposeMessage(llvm_triple);
|
||||
LLVMDisposeMessage(cpu);
|
||||
LLVMDisposeMessage(features);
|
||||
return true;
|
||||
|
||||
fail:
|
||||
if (lazy_orcjit)
|
||||
LLVMOrcDisposeLLLazyJIT(lazy_orcjit);
|
||||
if (tm_builder)
|
||||
LLVMOrcDisposeJITTargetMachineBuilder(tm_builder);
|
||||
if (lazy_orcjit_builder)
|
||||
LLVMOrcDisposeLLLazyJITBuilder(lazy_orcjit_builder);
|
||||
if (tm_opt2)
|
||||
LLVMDisposeTargetMachine(tm_opt2);
|
||||
if (tm_opt)
|
||||
LLVMDisposeTargetMachine(tm_opt);
|
||||
if (orc_symbol_map_pairs)
|
||||
wasm_runtime_free(orc_symbol_map_pairs);
|
||||
if (orc_call_through_mgr)
|
||||
LLVMOrcDisposeLazyCallThroughManager(orc_call_through_mgr);
|
||||
if (orc_indirect_stub_mgr)
|
||||
LLVMOrcDisposeIndirectStubsManager(orc_indirect_stub_mgr);
|
||||
if (orc_lazyjit)
|
||||
LLVMOrcDisposeLLJIT(orc_lazyjit);
|
||||
if (target_machine_builder)
|
||||
LLVMOrcDisposeJITTargetMachineBuilder(target_machine_builder);
|
||||
if (orc_lazyjit_builder)
|
||||
LLVMOrcDisposeLLJITBuilder(orc_lazyjit_builder);
|
||||
if (target_machine_for_orcjit)
|
||||
LLVMDisposeTargetMachine(target_machine_for_orcjit);
|
||||
if (features)
|
||||
LLVMDisposeMessage(features);
|
||||
if (cpu)
|
||||
LLVMDisposeMessage(cpu);
|
||||
if (llvm_triple)
|
||||
LLVMDisposeMessage(llvm_triple);
|
||||
aot_set_last_error(buf);
|
||||
return false;
|
||||
}
|
||||
#endif /* WASM_ENABLE_LAZY_JIT != 0 */
|
||||
|
@ -1371,7 +1438,6 @@ aot_create_comp_context(AOTCompData *comp_data, aot_comp_option_t option)
|
|||
#if WASM_ENABLE_LAZY_JIT == 0
|
||||
struct LLVMMCJITCompilerOptions jit_options;
|
||||
#endif
|
||||
|
||||
LLVMTargetRef target;
|
||||
char *triple = NULL, *triple_norm, *arch, *abi;
|
||||
char *cpu = NULL, *features, buf[128];
|
||||
|
@ -1379,7 +1445,7 @@ aot_create_comp_context(AOTCompData *comp_data, aot_comp_option_t option)
|
|||
char *err = NULL, *fp_round = "round.tonearest",
|
||||
*fp_exce = "fpexcept.strict";
|
||||
char triple_buf[32] = { 0 }, features_buf[128] = { 0 };
|
||||
uint32 opt_level, size_level;
|
||||
uint32 opt_level, size_level, i;
|
||||
LLVMCodeModel code_model;
|
||||
LLVMTargetDataRef target_data_ref;
|
||||
|
||||
|
@ -1408,14 +1474,17 @@ aot_create_comp_context(AOTCompData *comp_data, aot_comp_option_t option)
|
|||
|
||||
/* Create LLVM context, module and builder */
|
||||
#if WASM_ENABLE_LAZY_JIT != 0
|
||||
comp_ctx->ts_context = LLVMOrcCreateNewThreadSafeContext();
|
||||
if (!comp_ctx->ts_context) {
|
||||
comp_ctx->orc_thread_safe_context = LLVMOrcCreateNewThreadSafeContext();
|
||||
if (!comp_ctx->orc_thread_safe_context) {
|
||||
aot_set_last_error("create LLVM ThreadSafeContext failed.");
|
||||
return NULL;
|
||||
goto fail;
|
||||
}
|
||||
/* Get a reference to the underlying LLVMContext */
|
||||
if (!(comp_ctx->context =
|
||||
LLVMOrcThreadSafeContextGetContext(comp_ctx->ts_context))) {
|
||||
|
||||
/* Get a reference to the underlying LLVMContext, note:
|
||||
different from non LAZY JIT mode, no need to dispose this context,
|
||||
if will be disposed when the thread safe context is disposed */
|
||||
if (!(comp_ctx->context = LLVMOrcThreadSafeContextGetContext(
|
||||
comp_ctx->orc_thread_safe_context))) {
|
||||
aot_set_last_error("get context from LLVM ThreadSafeContext failed.");
|
||||
goto fail;
|
||||
}
|
||||
|
@ -1431,17 +1500,41 @@ aot_create_comp_context(AOTCompData *comp_data, aot_comp_option_t option)
|
|||
goto fail;
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_LAZY_JIT == 0
|
||||
if (!(comp_ctx->module = LLVMModuleCreateWithNameInContext(
|
||||
"WASM Module", comp_ctx->context))) {
|
||||
aot_set_last_error("create LLVM module failed.");
|
||||
goto fail;
|
||||
}
|
||||
#else
|
||||
if (comp_data->func_count > 0) {
|
||||
if (!(comp_ctx->modules = wasm_runtime_malloc(
|
||||
sizeof(LLVMModuleRef) * comp_data->func_count))) {
|
||||
aot_set_last_error("allocate memory failed.");
|
||||
goto fail;
|
||||
}
|
||||
memset(comp_ctx->modules, 0,
|
||||
sizeof(LLVMModuleRef) * comp_data->func_count);
|
||||
for (i = 0; i < comp_data->func_count; i++) {
|
||||
char module_name[32];
|
||||
snprintf(module_name, sizeof(module_name), "WASM Module %d", i);
|
||||
/* Create individual modules for each aot function, note:
|
||||
different from non LAZY JIT mode, no need to dispose them,
|
||||
they will be disposed when the thread safe context is disposed */
|
||||
if (!(comp_ctx->modules[i] = LLVMModuleCreateWithNameInContext(
|
||||
module_name, comp_ctx->context))) {
|
||||
aot_set_last_error("create LLVM module failed.");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (BH_LIST_ERROR == bh_list_init(&comp_ctx->native_symbols)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_DEBUG_AOT != 0
|
||||
#if WASM_ENABLE_DEBUG_AOT != 0 && WASM_ENABLE_LAZY_JIT == 0
|
||||
if (!(comp_ctx->debug_builder = LLVMCreateDIBuilder(comp_ctx->module))) {
|
||||
aot_set_last_error("create LLVM Debug Infor builder failed.");
|
||||
goto fail;
|
||||
|
@ -1497,10 +1590,11 @@ aot_create_comp_context(AOTCompData *comp_data, aot_comp_option_t option)
|
|||
if (option->is_jit_mode) {
|
||||
char *triple_jit = NULL;
|
||||
|
||||
comp_ctx->is_jit_mode = true;
|
||||
|
||||
#if WASM_ENABLE_LAZY_JIT != 0
|
||||
/* Create LLLazyJIT Instance */
|
||||
if (!llvm_orcjit_create(comp_ctx)) {
|
||||
aot_set_last_error("create LLVM Lazy JIT Compiler failed.");
|
||||
/* Create LLJIT Instance */
|
||||
if (!orc_lazyjit_create(comp_ctx, comp_data->func_count)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
@ -1524,7 +1618,6 @@ aot_create_comp_context(AOTCompData *comp_data, aot_comp_option_t option)
|
|||
comp_ctx->target_machine =
|
||||
LLVMGetExecutionEngineTargetMachine(comp_ctx->exec_engine);
|
||||
#endif
|
||||
comp_ctx->is_jit_mode = true;
|
||||
|
||||
#ifndef OS_ENABLE_HW_BOUND_CHECK
|
||||
comp_ctx->enable_bound_check = true;
|
||||
|
@ -1533,8 +1626,8 @@ aot_create_comp_context(AOTCompData *comp_data, aot_comp_option_t option)
|
|||
#endif
|
||||
|
||||
#if WASM_ENABLE_LAZY_JIT != 0
|
||||
if (!(triple_jit = (char *)LLVMOrcLLLazyJITGetTripleString(
|
||||
comp_ctx->lazy_orcjit))) {
|
||||
if (!(triple_jit =
|
||||
(char *)LLVMOrcLLJITGetTripleString(comp_ctx->orc_lazyjit))) {
|
||||
aot_set_last_error("can not get triple from the target machine");
|
||||
goto fail;
|
||||
}
|
||||
|
@ -1768,9 +1861,17 @@ aot_create_comp_context(AOTCompData *comp_data, aot_comp_option_t option)
|
|||
aot_set_last_error("create metadata string failed.");
|
||||
goto fail;
|
||||
}
|
||||
#if WASM_ENABLE_LAZY_JIT == 0
|
||||
LLVMAddModuleFlag(comp_ctx->module, LLVMModuleFlagBehaviorError,
|
||||
"target-abi", strlen("target-abi"),
|
||||
meta_target_abi);
|
||||
#else
|
||||
for (i = 0; i < comp_data->func_count; i++) {
|
||||
LLVMAddModuleFlag(comp_ctx->modules[i],
|
||||
LLVMModuleFlagBehaviorError, "target-abi",
|
||||
strlen("target-abi"), meta_target_abi);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!strcmp(abi, "lp64d") || !strcmp(abi, "ilp32d")) {
|
||||
if (features) {
|
||||
|
@ -1878,7 +1979,9 @@ aot_create_comp_context(AOTCompData *comp_data, aot_comp_option_t option)
|
|||
goto fail;
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_LAZY_JIT == 0
|
||||
LLVMSetTarget(comp_ctx->module, triple_norm);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (option->enable_simd && strcmp(comp_ctx->target_arch, "x86_64") != 0
|
||||
|
@ -1921,11 +2024,18 @@ aot_create_comp_context(AOTCompData *comp_data, aot_comp_option_t option)
|
|||
if (option->output_format == AOT_LLVMIR_UNOPT_FILE)
|
||||
comp_ctx->optimize = false;
|
||||
|
||||
#if WASM_ENABLE_LAZY_JIT == 0
|
||||
if (!(comp_ctx->pass_mgr =
|
||||
LLVMCreateFunctionPassManagerForModule(comp_ctx->module))) {
|
||||
aot_set_last_error("create LLVM pass manager failed.");
|
||||
goto fail;
|
||||
}
|
||||
#else
|
||||
if (!(comp_ctx->pass_mgr = LLVMCreatePassManager())) {
|
||||
aot_set_last_error("create LLVM pass manager failed.");
|
||||
goto fail;
|
||||
}
|
||||
#endif
|
||||
|
||||
LLVMAddPromoteMemoryToRegisterPass(comp_ctx->pass_mgr);
|
||||
LLVMAddInstructionCombiningPass(comp_ctx->pass_mgr);
|
||||
|
@ -2012,6 +2122,7 @@ fail:
|
|||
if (!ret)
|
||||
aot_destroy_comp_context(comp_ctx);
|
||||
|
||||
(void)i;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -2022,25 +2133,42 @@ aot_destroy_comp_context(AOTCompContext *comp_ctx)
|
|||
return;
|
||||
|
||||
if (comp_ctx->pass_mgr) {
|
||||
#if WASM_ENABLE_LAZY_JIT == 0
|
||||
LLVMFinalizeFunctionPassManager(comp_ctx->pass_mgr);
|
||||
#endif
|
||||
LLVMDisposePassManager(comp_ctx->pass_mgr);
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_LAZY_JIT != 0
|
||||
if (comp_ctx->target_machine && comp_ctx->is_jit_mode)
|
||||
if (comp_ctx->orc_symbol_map_pairs)
|
||||
wasm_runtime_free(comp_ctx->orc_symbol_map_pairs);
|
||||
|
||||
if (comp_ctx->orc_call_through_mgr)
|
||||
LLVMOrcDisposeLazyCallThroughManager(comp_ctx->orc_call_through_mgr);
|
||||
|
||||
if (comp_ctx->orc_indirect_stub_mgr)
|
||||
LLVMOrcDisposeIndirectStubsManager(comp_ctx->orc_indirect_stub_mgr);
|
||||
|
||||
if (comp_ctx->orc_material_unit)
|
||||
LLVMOrcDisposeMaterializationUnit(comp_ctx->orc_material_unit);
|
||||
|
||||
if (comp_ctx->target_machine)
|
||||
LLVMDisposeTargetMachine(comp_ctx->target_machine);
|
||||
|
||||
if (comp_ctx->builder)
|
||||
LLVMDisposeBuilder(comp_ctx->builder);
|
||||
|
||||
if (comp_ctx->lazy_orcjit)
|
||||
LLVMOrcDisposeLLLazyJIT(comp_ctx->lazy_orcjit);
|
||||
if (comp_ctx->orc_lazyjit)
|
||||
LLVMOrcDisposeLLJIT(comp_ctx->orc_lazyjit);
|
||||
|
||||
if (comp_ctx->ts_context)
|
||||
LLVMOrcDisposeThreadSafeContext(comp_ctx->ts_context);
|
||||
if (comp_ctx->orc_thread_safe_context)
|
||||
LLVMOrcDisposeThreadSafeContext(comp_ctx->orc_thread_safe_context);
|
||||
|
||||
if (comp_ctx->tm_builder)
|
||||
LLVMOrcDisposeJITTargetMachineBuilder(comp_ctx->tm_builder);
|
||||
if (comp_ctx->modules)
|
||||
wasm_runtime_free(comp_ctx->modules);
|
||||
|
||||
/* Note: don't dispose comp_ctx->context and comp_ctx->modules[i] as
|
||||
they are disposed when disposing the thread safe context */
|
||||
|
||||
LLVMShutdown();
|
||||
#else
|
||||
|
@ -2237,7 +2365,7 @@ aot_block_stack_destroy(AOTBlockStack *stack)
|
|||
while (block) {
|
||||
p = block->next;
|
||||
aot_value_stack_destroy(&block->value_stack);
|
||||
wasm_runtime_free(block);
|
||||
aot_block_destroy(block);
|
||||
block = p;
|
||||
}
|
||||
}
|
||||
|
@ -2433,7 +2561,7 @@ __call_llvm_intrinsic(const AOTCompContext *comp_ctx,
|
|||
}
|
||||
else {
|
||||
/* Declare llvm intrinsic function if necessary */
|
||||
if (!(func = LLVMGetNamedFunction(comp_ctx->module, name))) {
|
||||
if (!(func = LLVMGetNamedFunction(func_ctx->module, name))) {
|
||||
if (!(func_type = LLVMFunctionType(ret_type, param_types,
|
||||
(uint32)param_count, false))) {
|
||||
aot_set_last_error(
|
||||
|
@ -2441,7 +2569,7 @@ __call_llvm_intrinsic(const AOTCompContext *comp_ctx,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
if (!(func = LLVMAddFunction(comp_ctx->module, name, func_type))) {
|
||||
if (!(func = LLVMAddFunction(func_ctx->module, name, func_type))) {
|
||||
aot_set_last_error("add LLVM intrinsic function failed.");
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -20,11 +20,14 @@
|
|||
#include "llvm-c/Transforms/PassManagerBuilder.h"
|
||||
|
||||
#if WASM_ENABLE_LAZY_JIT != 0
|
||||
#include "aot_llvm_lazyjit.h"
|
||||
#include "llvm-c/Orc.h"
|
||||
#include "llvm-c/Error.h"
|
||||
#include "llvm-c/Initialization.h"
|
||||
#include "llvm-c/Support.h"
|
||||
#include "llvm-c/Initialization.h"
|
||||
#include "llvm-c/TargetMachine.h"
|
||||
#if LLVM_VERSION_MAJOR >= 12
|
||||
#include "llvm-c/LLJIT.h"
|
||||
#endif
|
||||
#endif
|
||||
#if WASM_ENABLE_DEBUG_AOT != 0
|
||||
#include "llvm-c/DebugInfo.h"
|
||||
|
@ -128,6 +131,9 @@ typedef struct AOTFuncContext {
|
|||
AOTFunc *aot_func;
|
||||
LLVMValueRef func;
|
||||
LLVMTypeRef func_type;
|
||||
/* LLVM module for this function, note that in LAZY JIT mode,
|
||||
each aot function belongs to an individual module */
|
||||
LLVMModuleRef module;
|
||||
AOTBlockStack block_stack;
|
||||
|
||||
LLVMValueRef exec_env;
|
||||
|
@ -249,7 +255,12 @@ typedef struct AOTCompContext {
|
|||
|
||||
/* LLVM variables required to emit LLVM IR */
|
||||
LLVMContextRef context;
|
||||
#if WASM_ENABLE_LAZY_JIT == 0
|
||||
/* Create one module only for non LAZY JIT mode,
|
||||
for LAZY JIT mode, modules are created, each
|
||||
aot function has its own module */
|
||||
LLVMModuleRef module;
|
||||
#endif
|
||||
LLVMBuilderRef builder;
|
||||
#if WASM_ENABLE_DEBUG_AOT
|
||||
LLVMDIBuilderRef debug_builder;
|
||||
|
@ -266,12 +277,18 @@ typedef struct AOTCompContext {
|
|||
|
||||
/* LLVM execution engine required by JIT */
|
||||
#if WASM_ENABLE_LAZY_JIT != 0
|
||||
LLVMOrcLLLazyJITRef lazy_orcjit;
|
||||
LLVMOrcThreadSafeContextRef ts_context;
|
||||
LLVMOrcJITTargetMachineBuilderRef tm_builder;
|
||||
LLVMOrcLLJITRef orc_lazyjit;
|
||||
LLVMOrcMaterializationUnitRef orc_material_unit;
|
||||
LLVMOrcLazyCallThroughManagerRef orc_call_through_mgr;
|
||||
LLVMOrcIndirectStubsManagerRef orc_indirect_stub_mgr;
|
||||
LLVMOrcCSymbolAliasMapPairs orc_symbol_map_pairs;
|
||||
LLVMOrcThreadSafeContextRef orc_thread_safe_context;
|
||||
/* Each aot function has its own module */
|
||||
LLVMModuleRef *modules;
|
||||
#else
|
||||
LLVMExecutionEngineRef exec_engine;
|
||||
#endif
|
||||
|
||||
bool is_jit_mode;
|
||||
|
||||
/* AOT indirect mode flag & symbol list */
|
||||
|
@ -453,9 +470,19 @@ void
|
|||
aot_add_expand_memory_op_pass(LLVMPassManagerRef pass);
|
||||
|
||||
#if WASM_ENABLE_LAZY_JIT != 0
|
||||
LLVMOrcJITTargetMachineBuilderRef
|
||||
LLVMOrcJITTargetMachineBuilderCreateFromTargetMachine(LLVMTargetMachineRef TM);
|
||||
|
||||
void
|
||||
aot_handle_llvm_errmsg(char *error_buf, uint32 error_buf_size,
|
||||
const char *string, LLVMErrorRef error);
|
||||
LLVMOrcLLJITBuilderSetNumCompileThreads(LLVMOrcLLJITBuilderRef orcjit_builder,
|
||||
unsigned num_compile_threads);
|
||||
|
||||
void
|
||||
aot_handle_llvm_errmsg(const char *string, LLVMErrorRef err);
|
||||
|
||||
void *
|
||||
aot_lookup_orcjit_func(LLVMOrcLLJITRef orc_lazyjit, void *module_inst,
|
||||
uint32 func_idx);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include <llvm/ExecutionEngine/GenericValue.h>
|
||||
#include <llvm/ExecutionEngine/JITEventListener.h>
|
||||
#include <llvm/ExecutionEngine/RTDyldMemoryManager.h>
|
||||
#include <llvm/ExecutionEngine/Orc/LLJIT.h>
|
||||
#include <llvm/IR/DerivedTypes.h>
|
||||
#include <llvm/IR/Module.h>
|
||||
#include <llvm/IR/Instructions.h>
|
||||
|
@ -30,8 +31,12 @@
|
|||
#include <llvm/Target/TargetOptions.h>
|
||||
#include <llvm/Transforms/Utils/LowerMemIntrinsics.h>
|
||||
#include <cstring>
|
||||
#if WASM_ENABLE_LAZY_JIT != 0
|
||||
#include "../aot/aot_runtime.h"
|
||||
#endif
|
||||
|
||||
using namespace llvm;
|
||||
using namespace llvm::orc;
|
||||
|
||||
extern "C" LLVMBool
|
||||
WAMRCreateMCJITCompilerForModule(LLVMExecutionEngineRef *OutJIT,
|
||||
|
@ -262,6 +267,63 @@ aot_check_simd_compatibility(const char *arch_c_str, const char *cpu_c_str)
|
|||
#endif /* WASM_ENABLE_SIMD */
|
||||
}
|
||||
|
||||
#if LLVM_VERSION_MAJOR < 12
|
||||
LLVMOrcJITTargetMachineBuilderRef
|
||||
LLVMOrcJITTargetMachineBuilderFromTargetMachine(LLVMTargetMachineRef TM);
|
||||
|
||||
LLVMOrcJITTargetMachineBuilderRef
|
||||
LLVMOrcJITTargetMachineBuilderCreateFromTargetMachine(LLVMTargetMachineRef TM)
|
||||
{
|
||||
return LLVMOrcJITTargetMachineBuilderFromTargetMachine(TM);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_LAZY_JIT != 0
|
||||
|
||||
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LLJITBuilder, LLVMOrcLLJITBuilderRef)
|
||||
|
||||
void
|
||||
LLVMOrcLLJITBuilderSetNumCompileThreads(LLVMOrcLLJITBuilderRef orcjit_builder,
|
||||
unsigned num_compile_threads)
|
||||
{
|
||||
unwrap(orcjit_builder)->setNumCompileThreads(num_compile_threads);
|
||||
}
|
||||
|
||||
void *
|
||||
aot_lookup_orcjit_func(LLVMOrcLLJITRef orc_lazyjit, void *module_inst,
|
||||
uint32 func_idx)
|
||||
{
|
||||
char func_name[32], buf[128], *err_msg = NULL;
|
||||
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;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
if (func_ptrs[func_idx])
|
||||
return func_ptrs[func_idx];
|
||||
|
||||
snprintf(func_name, sizeof(func_name), "%s%d", AOT_FUNC_PREFIX,
|
||||
func_idx - aot_module->import_func_count);
|
||||
if ((error = LLVMOrcLLJITLookup(orc_lazyjit, &func_addr, func_name))) {
|
||||
err_msg = LLVMGetErrorMessage(error);
|
||||
snprintf(buf, sizeof(buf), "failed to lookup orcjit function: %s",
|
||||
err_msg);
|
||||
aot_set_exception(aot_inst, buf);
|
||||
LLVMDisposeErrorMessage(err_msg);
|
||||
return NULL;
|
||||
}
|
||||
func_ptrs[func_idx] = (void *)func_addr;
|
||||
return (void *)func_addr;
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
aot_func_disable_tce(LLVMValueRef func)
|
||||
{
|
||||
|
|
|
@ -1,120 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#include "aot_llvm_lazyjit.h"
|
||||
|
||||
LLVMOrcJITTargetMachineBuilderRef
|
||||
LLVMOrcJITTargetMachineBuilderFromTargetMachine(LLVMTargetMachineRef TM);
|
||||
|
||||
LLVMOrcLLJITBuilderRef
|
||||
LLVMOrcCreateLLJITBuilder(void);
|
||||
|
||||
void
|
||||
LLVMOrcDisposeLLJITBuilder(LLVMOrcLLJITBuilderRef Builder);
|
||||
|
||||
LLVMErrorRef
|
||||
LLVMOrcCreateLLJIT(LLVMOrcLLJITRef *Result, LLVMOrcLLJITBuilderRef Builder);
|
||||
|
||||
LLVMErrorRef
|
||||
LLVMOrcDisposeLLJIT(LLVMOrcLLJITRef J);
|
||||
|
||||
LLVMOrcJITDylibRef
|
||||
LLVMOrcLLJITGetMainJITDylib(LLVMOrcLLJITRef J);
|
||||
|
||||
const char *
|
||||
LLVMOrcLLJITGetTripleString(LLVMOrcLLJITRef J);
|
||||
|
||||
char
|
||||
LLVMOrcLLJITGetGlobalPrefix(LLVMOrcLLJITRef J);
|
||||
|
||||
LLVMErrorRef
|
||||
LLVMOrcLLJITAddLLVMIRModule(LLVMOrcLLJITRef J, LLVMOrcJITDylibRef JD,
|
||||
LLVMOrcThreadSafeModuleRef TSM);
|
||||
|
||||
LLVMErrorRef
|
||||
LLVMOrcLLJITLookup(LLVMOrcLLJITRef J, LLVMOrcJITTargetAddress *Result,
|
||||
const char *Name);
|
||||
|
||||
const char *
|
||||
LLVMOrcLLJITGetTripleString(LLVMOrcLLJITRef J);
|
||||
|
||||
void
|
||||
LLVMOrcLLJITBuilderSetJITTargetMachineBuilder(
|
||||
LLVMOrcLLJITBuilderRef Builder, LLVMOrcJITTargetMachineBuilderRef JTMB);
|
||||
|
||||
char
|
||||
LLVMOrcLLJITGetGlobalPrefix(LLVMOrcLLJITRef J);
|
||||
|
||||
#if LLVM_VERSION_MAJOR < 12
|
||||
LLVMOrcJITTargetMachineBuilderRef
|
||||
LLVMOrcJITTargetMachineBuilderCreateFromTargetMachine(LLVMTargetMachineRef TM)
|
||||
{
|
||||
return LLVMOrcJITTargetMachineBuilderFromTargetMachine(TM);
|
||||
}
|
||||
#endif
|
||||
|
||||
LLVMOrcJITDylibRef
|
||||
LLVMOrcLLLazyJITGetMainJITDylib(LLVMOrcLLLazyJITRef J)
|
||||
{
|
||||
return LLVMOrcLLJITGetMainJITDylib(J);
|
||||
}
|
||||
|
||||
LLVMOrcLLLazyJITBuilderRef
|
||||
LLVMOrcCreateLLLazyJITBuilder(void)
|
||||
{
|
||||
return LLVMOrcCreateLLJITBuilder();
|
||||
}
|
||||
|
||||
void
|
||||
LLVMOrcDisposeLLLazyJITBuilder(LLVMOrcLLLazyJITBuilderRef Builder)
|
||||
{
|
||||
return LLVMOrcDisposeLLJITBuilder(Builder);
|
||||
}
|
||||
|
||||
LLVMErrorRef
|
||||
LLVMOrcCreateLLLazyJIT(LLVMOrcLLLazyJITRef *Result,
|
||||
LLVMOrcLLLazyJITBuilderRef Builder)
|
||||
{
|
||||
return LLVMOrcCreateLLJIT(Result, Builder);
|
||||
}
|
||||
|
||||
LLVMErrorRef
|
||||
LLVMOrcDisposeLLLazyJIT(LLVMOrcLLLazyJITRef J)
|
||||
{
|
||||
return LLVMOrcDisposeLLJIT(J);
|
||||
}
|
||||
|
||||
LLVMErrorRef
|
||||
LLVMOrcLLLazyJITAddLLVMIRModule(LLVMOrcLLLazyJITRef J, LLVMOrcJITDylibRef JD,
|
||||
LLVMOrcThreadSafeModuleRef TSM)
|
||||
{
|
||||
return LLVMOrcLLJITAddLLVMIRModule(J, JD, TSM);
|
||||
}
|
||||
|
||||
LLVMErrorRef
|
||||
LLVMOrcLLLazyJITLookup(LLVMOrcLLLazyJITRef J, LLVMOrcJITTargetAddress *Result,
|
||||
const char *Name)
|
||||
{
|
||||
return LLVMOrcLLJITLookup(J, Result, Name);
|
||||
}
|
||||
|
||||
const char *
|
||||
LLVMOrcLLLazyJITGetTripleString(LLVMOrcLLLazyJITRef J)
|
||||
{
|
||||
return LLVMOrcLLJITGetTripleString(J);
|
||||
}
|
||||
|
||||
void
|
||||
LLVMOrcLLLazyJITBuilderSetJITTargetMachineBuilder(
|
||||
LLVMOrcLLLazyJITBuilderRef Builder, LLVMOrcJITTargetMachineBuilderRef JTMB)
|
||||
{
|
||||
return LLVMOrcLLJITBuilderSetJITTargetMachineBuilder(Builder, JTMB);
|
||||
}
|
||||
|
||||
char
|
||||
LLVMOrcLLLazyJITGetGlobalPrefix(LLVMOrcLLLazyJITRef J)
|
||||
{
|
||||
return LLVMOrcLLJITGetGlobalPrefix(J);
|
||||
}
|
|
@ -1,72 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#ifndef AOT_LLVM_LAZYJIT_H
|
||||
#define AOT_LLVM_LAZYJIT_H
|
||||
|
||||
#include "llvm-c/Error.h"
|
||||
#include "llvm-c/Orc.h"
|
||||
#include "llvm-c/TargetMachine.h"
|
||||
#include "llvm-c/Types.h"
|
||||
#if LLVM_VERSION_MAJOR >= 12
|
||||
#include "llvm-c/LLJIT.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef LLVMOrcLLJITBuilderRef LLVMOrcLLLazyJITBuilderRef;
|
||||
|
||||
typedef LLVMOrcLLJITRef LLVMOrcLLLazyJITRef;
|
||||
|
||||
LLVMOrcJITTargetMachineBuilderRef
|
||||
LLVMOrcJITTargetMachineBuilderCreateFromTargetMachine(LLVMTargetMachineRef TM);
|
||||
|
||||
LLVMOrcLLLazyJITBuilderRef
|
||||
LLVMOrcCreateLLLazyJITBuilder(void);
|
||||
|
||||
void
|
||||
LLVMOrcDisposeLLLazyJITBuilder(LLVMOrcLLLazyJITBuilderRef Builder);
|
||||
|
||||
LLVMErrorRef
|
||||
LLVMOrcCreateLLLazyJIT(LLVMOrcLLLazyJITRef *Result,
|
||||
LLVMOrcLLLazyJITBuilderRef Builder);
|
||||
|
||||
LLVMErrorRef
|
||||
LLVMOrcDisposeLLLazyJIT(LLVMOrcLLLazyJITRef J);
|
||||
|
||||
LLVMOrcJITDylibRef
|
||||
LLVMOrcLLLazyJITGetMainJITDylib(LLVMOrcLLLazyJITRef J);
|
||||
|
||||
const char *
|
||||
LLVMOrcLLLazyJITGetTripleString(LLVMOrcLLLazyJITRef J);
|
||||
|
||||
char
|
||||
LLVMOrcLLLazyJITGetGlobalPrefix(LLVMOrcLLLazyJITRef J);
|
||||
|
||||
LLVMErrorRef
|
||||
LLVMOrcLLLazyJITAddLLVMIRModule(LLVMOrcLLLazyJITRef J, LLVMOrcJITDylibRef JD,
|
||||
LLVMOrcThreadSafeModuleRef TSM);
|
||||
|
||||
LLVMErrorRef
|
||||
LLVMOrcLLLazyJITLookup(LLVMOrcLLLazyJITRef J, LLVMOrcJITTargetAddress *Result,
|
||||
const char *Name);
|
||||
|
||||
const char *
|
||||
LLVMOrcLLLazyJITGetTripleString(LLVMOrcLLLazyJITRef J);
|
||||
|
||||
void
|
||||
LLVMOrcLLLazyJITBuilderSetJITTargetMachineBuilder(
|
||||
LLVMOrcLLLazyJITBuilderRef Builder, LLVMOrcJITTargetMachineBuilderRef JTMB);
|
||||
|
||||
char
|
||||
LLVMOrcLLLazyJITGetGlobalPrefix(LLVMOrcLLLazyJITRef J);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* end of AOT_LLVM_LAZYJIT_H */
|
|
@ -32,7 +32,9 @@ os_thread_wrapper(void *arg)
|
|||
os_signal_handler handler = targ->signal_handler;
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
os_printf("THREAD CREATED %jx\n", (uintmax_t)(uintptr_t)pthread_self());
|
||||
#endif
|
||||
BH_FREE(targ);
|
||||
#ifdef OS_ENABLE_HW_BOUND_CHECK
|
||||
if (os_thread_signal_init(handler) != 0)
|
||||
|
|
|
@ -22,7 +22,9 @@ os_thread_wrapper(void *arg)
|
|||
thread_start_routine_t start_func = targ->start;
|
||||
void *thread_arg = targ->arg;
|
||||
|
||||
#if 0
|
||||
os_printf("THREAD CREATED %jx\n", (uintmax_t)(uintptr_t)pthread_self());
|
||||
#endif
|
||||
BH_FREE(targ);
|
||||
start_func(thread_arg);
|
||||
return NULL;
|
||||
|
|
|
@ -18,7 +18,10 @@ os_thread_wrapper(void *arg)
|
|||
thread_wrapper_arg *targ = arg;
|
||||
thread_start_routine_t start_func = targ->start;
|
||||
void *thread_arg = targ->arg;
|
||||
|
||||
#if 0
|
||||
os_printf("THREAD CREATED %p\n", &targ);
|
||||
#endif
|
||||
BH_FREE(targ);
|
||||
start_func(thread_arg);
|
||||
return NULL;
|
||||
|
|
|
@ -164,7 +164,9 @@ static unsigned __stdcall os_thread_wrapper(void *arg)
|
|||
void *retval;
|
||||
bool result;
|
||||
|
||||
#if 0
|
||||
os_printf("THREAD CREATED %p\n", thread_data);
|
||||
#endif
|
||||
|
||||
os_mutex_lock(&parent->wait_lock);
|
||||
thread_data->thread_id = GetCurrentThreadId();
|
||||
|
|
|
@ -41,7 +41,7 @@ cmake -DWAMR_BUILD_PLATFORM=linux -DWAMR_BUILD_TARGET=ARM
|
|||
|
||||
- **WAMR_BUILD_AOT**=1/0, default to enable if not set
|
||||
- **WAMR_BUILD_JIT**=1/0, default to disable if not set
|
||||
- **WAMR_BUILD_LAZY_JIT**=1/0, default to disable if not set
|
||||
- **WAMR_BUILD_LAZY_JIT**=1/0, whether to use Lazy JIT mode or not when *WAMR_BUILD_JIT* is set, default to enable if not set
|
||||
|
||||
#### **Configure LIBC**
|
||||
|
||||
|
@ -206,7 +206,7 @@ make
|
|||
```
|
||||
|
||||
|
||||
By default in Linux, the interpreter, AOT and WASI are enabled, and JIT and LazyJIT are disabled.
|
||||
By default in Linux, the interpreter, AOT and WASI are enabled, and JIT is disabled.
|
||||
And the build target is set to X86_64 or X86_32 depending on the platform's bitwidth.
|
||||
|
||||
To enable WASM JIT, firstly we should build LLVM:
|
||||
|
@ -225,10 +225,10 @@ cmake .. -DWAMR_BUILD_JIT=1
|
|||
make
|
||||
```
|
||||
|
||||
Moreover, pass arguments `-DWAMR_BUILD_JIT=1` and `-DWAMR_BUILD_LAZY_JIT=1` together to cmake to enable WASM Lazy JIT.
|
||||
If Lazy JIT is enabled, then jit function bodies in the module will not be compiled until they are first called,
|
||||
so compile time reduces significantly.
|
||||
|
||||
By default, the Lazy JIT is enabled to speedup the lanuching process and reduce the JIT compilation time
|
||||
by creating threads to compile the WASM functions parallely, and for the main thread, the functions in the
|
||||
module will not be compiled until they are firstly called and haven't been compiled by the compilation threads.
|
||||
To disable it, please pass argument `-DWAMR_BUILD_LAZY_JIT=0` to cmake.
|
||||
|
||||
Linux SGX (Intel Software Guard Extension)
|
||||
-------------------------
|
||||
|
|
|
@ -6,5 +6,5 @@
|
|||
rm -fr build && mkdir build
|
||||
cd build
|
||||
cmake .. -DWAMR_BUILD_JIT=1
|
||||
make
|
||||
make -j ${nroc}
|
||||
cd ..
|
||||
|
|
|
@ -6,5 +6,5 @@
|
|||
rm -fr build && mkdir build
|
||||
cd build
|
||||
cmake .. -DWAMR_BUILD_JIT=1
|
||||
make
|
||||
make -j ${nproc}
|
||||
cd ..
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
|
||||
rm -fr build && mkdir build
|
||||
cd build
|
||||
# Build With LazyJIT
|
||||
# cmake .. -DWAMR_BUILD_JIT=1 -DWAMR_BUILD_LAZY_JIT=1
|
||||
# By default LazyJIT is enabled, to disable it:
|
||||
# cmake .. -DWAMR_BUILD_JIT=1 -DWAMR_BUILD_LAZY_JIT=0
|
||||
cmake .. -DWAMR_BUILD_JIT=1
|
||||
make
|
||||
make -j ${nproc}
|
||||
cd ..
|
||||
|
|
Loading…
Reference in New Issue
Block a user