Implement call Fast JIT function from LLVM JIT jitted code (#1714)

Basically implement the Multi-tier JIT engine.
And update document and wamr-test-suites script.
This commit is contained in:
Wenyong Huang 2022-11-21 10:42:18 +08:00 committed by GitHub
parent 3daa512925
commit cf7b01ad82
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 1775 additions and 221 deletions

View File

@ -83,6 +83,13 @@ if (NOT WAMR_BUILD_AOT EQUAL 1)
endif () endif ()
endif () endif ()
if (WAMR_BUILD_FAST_JIT EQUAL 1)
if (NOT WAMR_BUILD_LAZY_JIT EQUAL 0)
# Enable Lazy JIT by default
set (WAMR_BUILD_LAZY_JIT 1)
endif ()
endif ()
if (WAMR_BUILD_JIT EQUAL 1) if (WAMR_BUILD_JIT EQUAL 1)
if (NOT WAMR_BUILD_LAZY_JIT EQUAL 0) if (NOT WAMR_BUILD_LAZY_JIT EQUAL 0)
# Enable Lazy JIT by default # Enable Lazy JIT by default
@ -134,7 +141,12 @@ else ()
message (" WAMR AOT disabled") message (" WAMR AOT disabled")
endif () endif ()
if (WAMR_BUILD_FAST_JIT EQUAL 1) if (WAMR_BUILD_FAST_JIT EQUAL 1)
message (" WAMR Fast JIT enabled") if (WAMR_BUILD_LAZY_JIT EQUAL 1)
add_definitions("-DWASM_ENABLE_LAZY_JIT=1")
message (" WAMR Fast JIT enabled with Lazy Compilation")
else ()
message (" WAMR Fast JIT enabled with Eager Compilation")
endif ()
else () else ()
message (" WAMR Fast JIT disabled") message (" WAMR Fast JIT disabled")
endif () endif ()
@ -149,6 +161,10 @@ if (WAMR_BUILD_JIT EQUAL 1)
else () else ()
message (" WAMR LLVM ORC JIT disabled") message (" WAMR LLVM ORC JIT disabled")
endif () endif ()
if (WAMR_BUILD_FAST_JIT EQUAL 1 AND WAMR_BUILD_JIT EQUAL 1
AND WAMR_BUILD_LAZY_JIT EQUAL 1)
message (" Multi-tier JIT enabled")
endif ()
if (WAMR_BUILD_LIBC_BUILTIN EQUAL 1) if (WAMR_BUILD_LIBC_BUILTIN EQUAL 1)
message (" Libc builtin enabled") message (" Libc builtin enabled")
else () else ()

View File

@ -2142,7 +2142,10 @@ static const char *exception_msgs[] = {
"wasm auxiliary stack underflow", /* EXCE_AUX_STACK_UNDERFLOW */ "wasm auxiliary stack underflow", /* EXCE_AUX_STACK_UNDERFLOW */
"out of bounds table access", /* EXCE_OUT_OF_BOUNDS_TABLE_ACCESS */ "out of bounds table access", /* EXCE_OUT_OF_BOUNDS_TABLE_ACCESS */
"wasm operand stack overflow", /* EXCE_OPERAND_STACK_OVERFLOW */ "wasm operand stack overflow", /* EXCE_OPERAND_STACK_OVERFLOW */
#if WASM_ENABLE_FAST_JIT != 0
"failed to compile fast jit function", /* EXCE_FAILED_TO_COMPILE_FAST_JIT_FUNC */
"", /* EXCE_ALREADY_THROWN */ "", /* EXCE_ALREADY_THROWN */
#endif
}; };
/* clang-format on */ /* clang-format on */

View File

@ -309,6 +309,8 @@ aot_get_imp_tbl_data_slots(const AOTImportTable *tbl, bool is_jit_mode)
#if WASM_ENABLE_MULTI_MODULE != 0 #if WASM_ENABLE_MULTI_MODULE != 0
if (is_jit_mode) if (is_jit_mode)
return tbl->table_max_size; return tbl->table_max_size;
#else
(void)is_jit_mode;
#endif #endif
return tbl->possible_grow ? tbl->table_max_size : tbl->table_init_size; return tbl->possible_grow ? tbl->table_max_size : tbl->table_init_size;
} }
@ -319,6 +321,8 @@ aot_get_tbl_data_slots(const AOTTable *tbl, bool is_jit_mode)
#if WASM_ENABLE_MULTI_MODULE != 0 #if WASM_ENABLE_MULTI_MODULE != 0
if (is_jit_mode) if (is_jit_mode)
return tbl->table_max_size; return tbl->table_max_size;
#else
(void)is_jit_mode;
#endif #endif
return tbl->possible_grow ? tbl->table_max_size : tbl->table_init_size; return tbl->possible_grow ? tbl->table_max_size : tbl->table_init_size;
} }

View File

@ -789,7 +789,53 @@ aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
func = func_ctx->func; func = func_ctx->func;
} }
else { else {
func = func_ctxes[func_idx - import_func_count]->func; if (!comp_ctx->is_jit_mode) {
func = func_ctxes[func_idx - import_func_count]->func;
}
else {
#if !(WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_LAZY_JIT != 0)
func = func_ctxes[func_idx - import_func_count]->func;
#else
/* JIT tier-up, load func ptr from func_ptrs[func_idx] */
LLVMValueRef func_ptr, func_idx_const;
LLVMTypeRef func_ptr_type;
if (!(func_idx_const = I32_CONST(func_idx))) {
aot_set_last_error("llvm build const failed.");
goto fail;
}
if (!(func_ptr = LLVMBuildInBoundsGEP2(
comp_ctx->builder, OPQ_PTR_TYPE,
func_ctx->func_ptrs, &func_idx_const, 1,
"func_ptr_tmp"))) {
aot_set_last_error("llvm build inbounds gep failed.");
goto fail;
}
if (!(func_ptr =
LLVMBuildLoad2(comp_ctx->builder, OPQ_PTR_TYPE,
func_ptr, "func_ptr"))) {
aot_set_last_error("llvm build load failed.");
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_ptr,
func_ptr_type,
"indirect_func"))) {
aot_set_last_error("llvm build bit cast failed.");
goto fail;
}
#endif /* end of !(WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_LAZY_JIT != 0) */
}
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -409,7 +409,7 @@ jit_compile_op_call(JitCompContext *cc, uint32 func_idx, bool tail_call)
res = create_first_res_reg(cc, func_type); res = create_first_res_reg(cc, func_type);
GEN_INSN(CALLBC, res, 0, jitted_code); GEN_INSN(CALLBC, res, 0, jitted_code, NEW_CONST(I32, func_idx));
if (!post_return(cc, func_type, res, true)) { if (!post_return(cc, func_type, res, true)) {
goto fail; goto fail;
@ -700,7 +700,7 @@ jit_compile_op_call_indirect(JitCompContext *cc, uint32 type_idx,
goto fail; goto fail;
} }
} }
GEN_INSN(CALLBC, res, 0, jitted_code); GEN_INSN(CALLBC, res, 0, jitted_code, func_idx);
/* Store res into current frame, so that post_return in /* Store res into current frame, so that post_return in
block func_return can get the value */ block func_return can get the value */
n = cc->jit_frame->sp - cc->jit_frame->lp; n = cc->jit_frame->sp - cc->jit_frame->lp;

View File

@ -58,8 +58,7 @@ jit_pass_register_jitted_code(JitCompContext *cc)
{ {
uint32 jit_func_idx = uint32 jit_func_idx =
cc->cur_wasm_func_idx - cc->cur_wasm_module->import_function_count; cc->cur_wasm_func_idx - cc->cur_wasm_module->import_function_count;
cc->cur_wasm_func->fast_jit_jitted_code = cc->jitted_addr_begin;
cc->cur_wasm_module->fast_jit_func_ptrs[jit_func_idx] = cc->cur_wasm_module->fast_jit_func_ptrs[jit_func_idx] =
cc->jitted_addr_begin; cc->cur_wasm_func->fast_jit_jitted_code = cc->jitted_addr_begin;
return true; return true;
} }

View File

@ -65,6 +65,14 @@ jit_codegen_gen_native(JitCompContext *cc);
bool bool
jit_codegen_lower(JitCompContext *cc); jit_codegen_lower(JitCompContext *cc);
#if WASM_ENABLE_LAZY_JIT != 0 && WASM_ENABLE_JIT != 0
void *
jit_codegen_compile_call_to_llvm_jit(const WASMType *func_type);
void *
jit_codegen_compile_call_to_fast_jit(const WASMModule *module, uint32 func_idx);
#endif
/** /**
* Dump native code in the given range to assembly. * Dump native code in the given range to assembly.
* *
@ -75,7 +83,8 @@ void
jit_codegen_dump_native(void *begin_addr, void *end_addr); jit_codegen_dump_native(void *begin_addr, void *end_addr);
int int
jit_codegen_interp_jitted_glue(void *self, JitInterpSwitchInfo *info, void *pc); jit_codegen_interp_jitted_glue(void *self, JitInterpSwitchInfo *info,
uint32 func_idx, void *pc);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -10,9 +10,9 @@
#include "../interpreter/wasm.h" #include "../interpreter/wasm.h"
typedef struct JitCompilerPass { typedef struct JitCompilerPass {
/* Name of the pass. */ /* Name of the pass */
const char *name; const char *name;
/* The entry of the compiler pass. */ /* The entry of the compiler pass */
bool (*run)(JitCompContext *cc); bool (*run)(JitCompContext *cc);
} JitCompilerPass; } JitCompilerPass;
@ -30,7 +30,7 @@ static JitCompilerPass compiler_passes[] = {
#undef REG_PASS #undef REG_PASS
}; };
/* Number of compiler passes. */ /* Number of compiler passes */
#define COMPILER_PASS_NUM (sizeof(compiler_passes) / sizeof(compiler_passes[0])) #define COMPILER_PASS_NUM (sizeof(compiler_passes) / sizeof(compiler_passes[0]))
#if WASM_ENABLE_FAST_JIT_DUMP == 0 #if WASM_ENABLE_FAST_JIT_DUMP == 0
@ -43,14 +43,17 @@ static const uint8 compiler_passes_with_dump[] = {
}; };
#endif #endif
/* The exported global data of JIT compiler. */ /* The exported global data of JIT compiler */
static JitGlobals jit_globals = { static JitGlobals jit_globals = {
#if WASM_ENABLE_FAST_JIT_DUMP == 0 #if WASM_ENABLE_FAST_JIT_DUMP == 0
.passes = compiler_passes_without_dump, .passes = compiler_passes_without_dump,
#else #else
.passes = compiler_passes_with_dump, .passes = compiler_passes_with_dump,
#endif #endif
.return_to_interp_from_jitted = NULL .return_to_interp_from_jitted = NULL,
#if WASM_ENABLE_LAZY_JIT != 0
.compile_fast_jit_and_then_call = NULL,
#endif
}; };
/* clang-format on */ /* clang-format on */
@ -60,7 +63,7 @@ apply_compiler_passes(JitCompContext *cc)
const uint8 *p = jit_globals.passes; const uint8 *p = jit_globals.passes;
for (; *p; p++) { for (; *p; p++) {
/* Set the pass NO. */ /* Set the pass NO */
cc->cur_pass_no = p - jit_globals.passes; cc->cur_pass_no = p - jit_globals.passes;
bh_assert(*p < COMPILER_PASS_NUM); bh_assert(*p < COMPILER_PASS_NUM);
@ -120,37 +123,53 @@ jit_compiler_get_pass_name(unsigned i)
bool bool
jit_compiler_compile(WASMModule *module, uint32 func_idx) jit_compiler_compile(WASMModule *module, uint32 func_idx)
{ {
JitCompContext *cc; JitCompContext *cc = NULL;
char *last_error; char *last_error;
bool ret = true; bool ret = false;
uint32 i = func_idx - module->import_function_count;
uint32 j = i % WASM_ORC_JIT_BACKEND_THREAD_NUM;
/* Initialize compilation context. */ /* Lock to avoid duplicated compilation by other threads */
if (!(cc = jit_calloc(sizeof(*cc)))) os_mutex_lock(&module->fast_jit_thread_locks[j]);
return false;
if (jit_compiler_is_compiled(module, func_idx)) {
/* Function has been compiled */
os_mutex_unlock(&module->fast_jit_thread_locks[j]);
return true;
}
/* Initialize the compilation context */
if (!(cc = jit_calloc(sizeof(*cc)))) {
goto fail;
}
if (!jit_cc_init(cc, 64)) { if (!jit_cc_init(cc, 64)) {
jit_free(cc); goto fail;
return false;
} }
cc->cur_wasm_module = module; cc->cur_wasm_module = module;
cc->cur_wasm_func = cc->cur_wasm_func = module->functions[i];
module->functions[func_idx - module->import_function_count];
cc->cur_wasm_func_idx = func_idx; cc->cur_wasm_func_idx = func_idx;
cc->mem_space_unchanged = (!cc->cur_wasm_func->has_op_memory_grow cc->mem_space_unchanged = (!cc->cur_wasm_func->has_op_memory_grow
&& !cc->cur_wasm_func->has_op_func_call) && !cc->cur_wasm_func->has_op_func_call)
|| (!module->possible_memory_grow); || (!module->possible_memory_grow);
/* Apply compiler passes. */ /* Apply compiler passes */
if (!apply_compiler_passes(cc) || jit_get_last_error(cc)) { if (!apply_compiler_passes(cc) || jit_get_last_error(cc)) {
last_error = jit_get_last_error(cc); last_error = jit_get_last_error(cc);
os_printf("fast jit compilation failed: %s\n", os_printf("fast jit compilation failed: %s\n",
last_error ? last_error : "unknown error"); last_error ? last_error : "unknown error");
ret = false; goto fail;
} }
/* Delete the compilation context. */ ret = true;
jit_cc_delete(cc);
fail:
/* Destroy the compilation context */
if (cc)
jit_cc_delete(cc);
os_mutex_unlock(&module->fast_jit_thread_locks[j]);
return ret; return ret;
} }
@ -169,8 +188,92 @@ jit_compiler_compile_all(WASMModule *module)
return true; return true;
} }
int bool
jit_interp_switch_to_jitted(void *exec_env, JitInterpSwitchInfo *info, void *pc) jit_compiler_is_compiled(const WASMModule *module, uint32 func_idx)
{ {
return jit_codegen_interp_jitted_glue(exec_env, info, pc); uint32 i = func_idx - module->import_function_count;
bh_assert(func_idx >= module->import_function_count
&& func_idx
< module->import_function_count + module->function_count);
#if WASM_ENABLE_LAZY_JIT == 0
return module->fast_jit_func_ptrs[i] ? true : false;
#else
return module->fast_jit_func_ptrs[i]
!= jit_globals.compile_fast_jit_and_then_call
? true
: false;
#endif
}
#if WASM_ENABLE_LAZY_JIT != 0 && WASM_ENABLE_JIT != 0
bool
jit_compiler_set_call_to_llvm_jit(WASMModule *module, uint32 func_idx)
{
uint32 i = func_idx - module->import_function_count;
uint32 j = i % WASM_ORC_JIT_BACKEND_THREAD_NUM;
WASMType *func_type = module->functions[i]->func_type;
uint32 k =
((uint32)(uintptr_t)func_type >> 3) % WASM_ORC_JIT_BACKEND_THREAD_NUM;
void *func_ptr = NULL;
/* Compile code block of call_to_llvm_jit_from_fast_jit of
this kind of function type if it hasn't been compiled */
if (!(func_ptr = func_type->call_to_llvm_jit_from_fast_jit)) {
os_mutex_lock(&module->fast_jit_thread_locks[k]);
if (!(func_ptr = func_type->call_to_llvm_jit_from_fast_jit)) {
if (!(func_ptr = func_type->call_to_llvm_jit_from_fast_jit =
jit_codegen_compile_call_to_llvm_jit(func_type))) {
os_mutex_unlock(&module->fast_jit_thread_locks[k]);
return false;
}
}
os_mutex_unlock(&module->fast_jit_thread_locks[k]);
}
/* Switch current fast jit func ptr to the code block */
os_mutex_lock(&module->fast_jit_thread_locks[j]);
module->fast_jit_func_ptrs[i] = func_ptr;
os_mutex_unlock(&module->fast_jit_thread_locks[j]);
return true;
}
bool
jit_compiler_set_call_to_fast_jit(WASMModule *module, uint32 func_idx)
{
void *func_ptr = NULL;
func_ptr = jit_codegen_compile_call_to_fast_jit(module, func_idx);
if (func_ptr) {
jit_compiler_set_llvm_jit_func_ptr(module, func_idx, func_ptr);
}
return func_ptr ? true : false;
}
void
jit_compiler_set_llvm_jit_func_ptr(WASMModule *module, uint32 func_idx,
void *func_ptr)
{
WASMModuleInstance *instance;
uint32 i = func_idx - module->import_function_count;
module->functions[i]->llvm_jit_func_ptr = module->func_ptrs[i] = func_ptr;
os_mutex_lock(&module->instance_list_lock);
instance = module->instance_list;
while (instance) {
instance->func_ptrs[func_idx] = func_ptr;
instance = instance->e->next;
}
os_mutex_unlock(&module->instance_list_lock);
}
#endif /* end of WASM_ENABLE_LAZY_JIT != 0 && WASM_ENABLE_JIT != 0 */
int
jit_interp_switch_to_jitted(void *exec_env, JitInterpSwitchInfo *info,
uint32 func_idx, void *pc)
{
return jit_codegen_interp_jitted_glue(exec_env, info, func_idx, pc);
} }

View File

@ -18,6 +18,9 @@ typedef struct JitGlobals {
/* Compiler pass sequence, the last element must be 0 */ /* Compiler pass sequence, the last element must be 0 */
const uint8 *passes; const uint8 *passes;
char *return_to_interp_from_jitted; char *return_to_interp_from_jitted;
#if WASM_ENABLE_LAZY_JIT != 0
char *compile_fast_jit_and_then_call;
#endif
} JitGlobals; } JitGlobals;
/** /**
@ -87,8 +90,24 @@ jit_compiler_compile(WASMModule *module, uint32 func_idx);
bool bool
jit_compiler_compile_all(WASMModule *module); jit_compiler_compile_all(WASMModule *module);
bool
jit_compiler_is_compiled(const WASMModule *module, uint32 func_idx);
#if WASM_ENABLE_LAZY_JIT != 0 && WASM_ENABLE_JIT != 0
bool
jit_compiler_set_call_to_llvm_jit(WASMModule *module, uint32 func_idx);
bool
jit_compiler_set_call_to_fast_jit(WASMModule *module, uint32 func_idx);
void
jit_compiler_set_llvm_jit_func_ptr(WASMModule *module, uint32 func_idx,
void *func_ptr);
#endif
int int
jit_interp_switch_to_jitted(void *self, JitInterpSwitchInfo *info, void *pc); jit_interp_switch_to_jitted(void *self, JitInterpSwitchInfo *info,
uint32 func_idx, void *pc);
/* /*
* Pass declarations: * Pass declarations:

View File

@ -2263,6 +2263,12 @@ jit_frontend_translate_func(JitCompContext *cc)
return basic_block_entry; return basic_block_entry;
} }
uint32
jit_frontend_get_jitted_return_addr_offset()
{
return (uint32)offsetof(WASMInterpFrame, jitted_return_addr);
}
#if 0 #if 0
#if WASM_ENABLE_THREAD_MGR != 0 #if WASM_ENABLE_THREAD_MGR != 0
bool bool

View File

@ -13,6 +13,10 @@
#include "../aot/aot_runtime.h" #include "../aot/aot_runtime.h"
#endif #endif
#ifdef __cplusplus
extern "C" {
#endif
#if WASM_ENABLE_AOT == 0 #if WASM_ENABLE_AOT == 0
typedef enum IntCond { typedef enum IntCond {
INT_EQZ = 0, INT_EQZ = 0,
@ -143,6 +147,9 @@ jit_frontend_translate_func(JitCompContext *cc);
bool bool
jit_frontend_lower(JitCompContext *cc); jit_frontend_lower(JitCompContext *cc);
uint32
jit_frontend_get_jitted_return_addr_offset();
uint32 uint32
jit_frontend_get_global_data_offset(const WASMModule *module, jit_frontend_get_global_data_offset(const WASMModule *module,
uint32 global_idx); uint32 global_idx);
@ -483,4 +490,8 @@ set_local_f64(JitFrame *frame, int n, JitReg val)
#define PUSH_FUNCREF(v) PUSH(v, VALUE_TYPE_FUNCREF) #define PUSH_FUNCREF(v) PUSH(v, VALUE_TYPE_FUNCREF)
#define PUSH_EXTERNREF(v) PUSH(v, VALUE_TYPE_EXTERNREF) #define PUSH_EXTERNREF(v) PUSH(v, VALUE_TYPE_EXTERNREF)
#ifdef __cplusplus
}
#endif
#endif #endif

View File

@ -196,7 +196,7 @@ INSN(LOOKUPSWITCH, LookupSwitch, 1, 0)
/* Call and return instructions */ /* Call and return instructions */
INSN(CALLNATIVE, VReg, 2, 1) INSN(CALLNATIVE, VReg, 2, 1)
INSN(CALLBC, Reg, 3, 2) INSN(CALLBC, Reg, 4, 2)
INSN(RETURNBC, Reg, 3, 0) INSN(RETURNBC, Reg, 3, 0)
INSN(RETURN, Reg, 1, 0) INSN(RETURN, Reg, 1, 0)

View File

@ -124,6 +124,12 @@ typedef struct WASMType {
uint16 param_cell_num; uint16 param_cell_num;
uint16 ret_cell_num; uint16 ret_cell_num;
uint16 ref_count; uint16 ref_count;
#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
&& WASM_ENABLE_LAZY_JIT != 0
/* Code block to call llvm jit functions of this
kind of function type from fast jit jitted code */
void *call_to_llvm_jit_from_fast_jit;
#endif
/* types of params and results */ /* types of params and results */
uint8 types[1]; uint8 types[1];
} WASMType; } WASMType;
@ -256,13 +262,6 @@ struct WASMFunction {
uint32 const_cell_num; uint32 const_cell_num;
#endif #endif
#if WASM_ENABLE_FAST_JIT != 0
void *fast_jit_jitted_code;
#endif
#if WASM_ENABLE_JIT != 0
void *llvm_jit_func_ptr;
#endif
#if WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0 \ #if WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0 \
|| WASM_ENABLE_WAMR_COMPILER != 0 || WASM_ENABLE_WAMR_COMPILER != 0
/* Whether function has opcode memory.grow */ /* Whether function has opcode memory.grow */
@ -278,6 +277,13 @@ struct WASMFunction {
/* Whether function has opcode set_global_aux_stack */ /* Whether function has opcode set_global_aux_stack */
bool has_op_set_global_aux_stack; bool has_op_set_global_aux_stack;
#endif #endif
#if WASM_ENABLE_FAST_JIT != 0
void *fast_jit_jitted_code;
#if WASM_ENABLE_JIT != 0 && WASM_ENABLE_LAZY_JIT != 0
void *llvm_jit_func_ptr;
#endif
#endif
}; };
struct WASMGlobal { struct WASMGlobal {
@ -378,18 +384,22 @@ typedef struct WASMCustomSection {
} WASMCustomSection; } WASMCustomSection;
#endif #endif
#if WASM_ENABLE_JIT != 0 #if WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0
struct AOTCompData; struct AOTCompData;
struct AOTCompContext; struct AOTCompContext;
/* Orc JIT thread arguments */ /* Orc JIT thread arguments */
typedef struct OrcJitThreadArg { typedef struct OrcJitThreadArg {
#if WASM_ENABLE_JIT != 0
struct AOTCompContext *comp_ctx; struct AOTCompContext *comp_ctx;
#endif
struct WASMModule *module; struct WASMModule *module;
uint32 group_idx; uint32 group_idx;
} OrcJitThreadArg; } OrcJitThreadArg;
#endif #endif
struct WASMModuleInstance;
struct WASMModule { struct WASMModule {
/* Module type, for module loaded from WASM bytecode binary, /* Module type, for module loaded from WASM bytecode binary,
this field is Wasm_Module_Bytecode; this field is Wasm_Module_Bytecode;
@ -496,18 +506,22 @@ struct WASMModule {
uint64 load_size; uint64 load_size;
#endif #endif
#if WASM_ENABLE_DEBUG_INTERP != 0 #if WASM_ENABLE_DEBUG_INTERP != 0 \
|| (WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT \
&& WASM_ENABLE_LAZY_JIT != 0)
/** /**
* Count how many instances reference this module. When source * List of instances referred to this module. When source debugging
* debugging feature enabled, the debugger may modify the code * feature is enabled, the debugger may modify the code section of
* section of the module, so we need to report a warning if user * the module, so we need to report a warning if user create several
* create several instances based on the same module * instances based on the same module. Sub instances created by
* lib-pthread or spawn API won't be added into the list.
* *
* Sub_instances created by lib-pthread or spawn API will not * Also add the instance to the list for Fast JIT to LLVM JIT
* influence or check the ref count * tier-up, since we need to lazily update the LLVM func pointers
* in the instance.
*/ */
uint32 ref_count; struct WASMModuleInstance *instance_list;
korp_mutex ref_count_lock; korp_mutex instance_list_lock;
#endif #endif
#if WASM_ENABLE_CUSTOM_NAME_SECTION != 0 #if WASM_ENABLE_CUSTOM_NAME_SECTION != 0
@ -522,6 +536,9 @@ struct WASMModule {
#if WASM_ENABLE_FAST_JIT != 0 #if WASM_ENABLE_FAST_JIT != 0
/* func pointers of Fast JITed (un-imported) functions */ /* func pointers of Fast JITed (un-imported) functions */
void **fast_jit_func_ptrs; void **fast_jit_func_ptrs;
/* locks for Fast JIT lazy compilation */
korp_mutex fast_jit_thread_locks[WASM_ORC_JIT_BACKEND_THREAD_NUM];
bool fast_jit_thread_locks_inited[WASM_ORC_JIT_BACKEND_THREAD_NUM];
#endif #endif
#if WASM_ENABLE_JIT != 0 #if WASM_ENABLE_JIT != 0
@ -531,9 +548,27 @@ struct WASMModule {
void **func_ptrs; void **func_ptrs;
/* whether the func pointers are compiled */ /* whether the func pointers are compiled */
bool *func_ptrs_compiled; bool *func_ptrs_compiled;
bool orcjit_stop_compiling; #endif
#if WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0
/* backend compilation threads */
korp_tid orcjit_threads[WASM_ORC_JIT_BACKEND_THREAD_NUM]; korp_tid orcjit_threads[WASM_ORC_JIT_BACKEND_THREAD_NUM];
/* backend thread arguments */
OrcJitThreadArg orcjit_thread_args[WASM_ORC_JIT_BACKEND_THREAD_NUM]; OrcJitThreadArg orcjit_thread_args[WASM_ORC_JIT_BACKEND_THREAD_NUM];
/* whether to stop the compilation of backend threads */
bool orcjit_stop_compiling;
#endif
#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
&& WASM_ENABLE_LAZY_JIT != 0
/* wait lock/cond for the synchronization of
the llvm jit initialization */
korp_mutex tierup_wait_lock;
korp_cond tierup_wait_cond;
bool tierup_wait_lock_inited;
korp_tid llvm_jit_init_thread;
/* whether the llvm jit is initialized */
bool llvm_jit_inited;
#endif #endif
}; };

View File

@ -3886,28 +3886,48 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
#if WASM_ENABLE_FAST_JIT != 0 #if WASM_ENABLE_FAST_JIT != 0
static void static void
fast_jit_call_func_bytecode(WASMExecEnv *exec_env, fast_jit_call_func_bytecode(WASMModuleInstance *module_inst,
WASMExecEnv *exec_env,
WASMFunctionInstance *function, WASMFunctionInstance *function,
WASMInterpFrame *frame) WASMInterpFrame *frame)
{ {
JitGlobals *jit_globals = jit_compiler_get_jit_globals(); JitGlobals *jit_globals = jit_compiler_get_jit_globals();
JitInterpSwitchInfo info; JitInterpSwitchInfo info;
WASMModule *module = module_inst->module;
WASMType *func_type = function->u.func->func_type; WASMType *func_type = function->u.func->func_type;
uint8 type = func_type->result_count uint8 type = func_type->result_count
? func_type->types[func_type->param_count] ? func_type->types[func_type->param_count]
: VALUE_TYPE_VOID; : VALUE_TYPE_VOID;
uint32 func_idx = (uint32)(function - module_inst->e->functions);
uint32 func_idx_non_import = func_idx - module->import_function_count;
int32 action;
#if WASM_ENABLE_REF_TYPES != 0 #if WASM_ENABLE_REF_TYPES != 0
if (type == VALUE_TYPE_EXTERNREF || type == VALUE_TYPE_FUNCREF) if (type == VALUE_TYPE_EXTERNREF || type == VALUE_TYPE_FUNCREF)
type = VALUE_TYPE_I32; type = VALUE_TYPE_I32;
#endif #endif
#if WASM_ENABLE_LAZY_JIT != 0
if (!jit_compiler_compile(module, func_idx)) {
wasm_set_exception(module_inst, "failed to compile fast jit function");
return;
}
#endif
bh_assert(jit_compiler_is_compiled(module, func_idx));
/* Switch to jitted code to call the jit function */
info.out.ret.last_return_type = type; info.out.ret.last_return_type = type;
info.frame = frame; info.frame = frame;
frame->jitted_return_addr = frame->jitted_return_addr =
(uint8 *)jit_globals->return_to_interp_from_jitted; (uint8 *)jit_globals->return_to_interp_from_jitted;
jit_interp_switch_to_jitted(exec_env, &info, action = jit_interp_switch_to_jitted(
function->u.func->fast_jit_jitted_code); exec_env, &info, func_idx,
module_inst->fast_jit_func_ptrs[func_idx_non_import]);
bh_assert(action == JIT_INTERP_ACTION_NORMAL
|| (action == JIT_INTERP_ACTION_THROWN
&& wasm_runtime_get_exception(exec_env->module_inst)));
/* Get the return values form info.out.ret */
if (func_type->result_count) { if (func_type->result_count) {
switch (type) { switch (type) {
case VALUE_TYPE_I32: case VALUE_TYPE_I32:
@ -3931,8 +3951,10 @@ fast_jit_call_func_bytecode(WASMExecEnv *exec_env,
break; break;
} }
} }
(void)action;
(void)func_idx;
} }
#endif #endif /* end of WASM_ENABLE_FAST_JIT != 0 */
#if WASM_ENABLE_JIT != 0 #if WASM_ENABLE_JIT != 0
static bool static bool
@ -3962,11 +3984,14 @@ llvm_jit_call_func_bytecode(WASMModuleInstance *module_inst,
WASMType *func_type = function->u.func->func_type; WASMType *func_type = function->u.func->func_type;
uint32 result_count = func_type->result_count; uint32 result_count = func_type->result_count;
uint32 ext_ret_count = result_count > 1 ? result_count - 1 : 0; uint32 ext_ret_count = result_count > 1 ? result_count - 1 : 0;
uint32 func_idx = (uint32)(function - module_inst->e->functions);
bool ret; bool ret;
#if (WASM_ENABLE_DUMP_CALL_STACK != 0) || (WASM_ENABLE_PERF_PROFILING != 0) #if (WASM_ENABLE_DUMP_CALL_STACK != 0) || (WASM_ENABLE_PERF_PROFILING != 0)
if (!llvm_jit_alloc_frame(exec_env, function - module_inst->e->functions)) { if (!llvm_jit_alloc_frame(exec_env, function - module_inst->e->functions)) {
wasm_set_exception(module_inst, "wasm operand stack overflow"); /* wasm operand stack overflow has been thrown,
no need to throw again */
return false;
} }
#endif #endif
@ -4007,8 +4032,8 @@ llvm_jit_call_func_bytecode(WASMModuleInstance *module_inst,
} }
ret = wasm_runtime_invoke_native( ret = wasm_runtime_invoke_native(
exec_env, function->u.func->llvm_jit_func_ptr, func_type, NULL, exec_env, module_inst->func_ptrs[func_idx], func_type, NULL, NULL,
NULL, argv1, argc, argv); argv1, argc, argv);
if (!ret || wasm_get_exception(module_inst)) { if (!ret || wasm_get_exception(module_inst)) {
if (clear_wasi_proc_exit_exception(module_inst)) if (clear_wasi_proc_exit_exception(module_inst))
@ -4058,8 +4083,8 @@ llvm_jit_call_func_bytecode(WASMModuleInstance *module_inst,
} }
else { else {
ret = wasm_runtime_invoke_native( ret = wasm_runtime_invoke_native(
exec_env, function->u.func->llvm_jit_func_ptr, func_type, NULL, exec_env, module_inst->func_ptrs[func_idx], func_type, NULL, NULL,
NULL, argv, argc, argv); argv, argc, argv);
if (clear_wasi_proc_exit_exception(module_inst)) if (clear_wasi_proc_exit_exception(module_inst))
ret = true; ret = true;
@ -4067,7 +4092,7 @@ llvm_jit_call_func_bytecode(WASMModuleInstance *module_inst,
return ret && !wasm_get_exception(module_inst) ? true : false; return ret && !wasm_get_exception(module_inst) ? true : false;
} }
} }
#endif #endif /* end of WASM_ENABLE_JIT != 0 */
void void
wasm_interp_call_wasm(WASMModuleInstance *module_inst, WASMExecEnv *exec_env, wasm_interp_call_wasm(WASMModuleInstance *module_inst, WASMExecEnv *exec_env,
@ -4134,18 +4159,63 @@ wasm_interp_call_wasm(WASMModuleInstance *module_inst, WASMExecEnv *exec_env,
} }
} }
else { else {
#if WASM_ENABLE_JIT != 0 #if WASM_ENABLE_LAZY_JIT != 0
/* Fast JIT to LLVM JIT tier-up is enabled */
#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0
/* Fast JIT and LLVM JIT are both enabled, call llvm jit function
if it is compiled, else call fast jit function */
uint32 func_idx = (uint32)(function - module_inst->e->functions);
if (module_inst->module->func_ptrs_compiled
[func_idx - module_inst->module->import_function_count]) {
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;
}
else {
fast_jit_call_func_bytecode(module_inst, exec_env, function, frame);
}
#elif WASM_ENABLE_JIT != 0
/* Only LLVM JIT is enabled */
llvm_jit_call_func_bytecode(module_inst, exec_env, function, argc, llvm_jit_call_func_bytecode(module_inst, exec_env, function, argc,
argv); argv);
/* For llvm jit, the results have been stored in argv, /* For llvm jit, the results have been stored in argv,
no need to copy them from stack frame again */ no need to copy them from stack frame again */
copy_argv_from_frame = false; copy_argv_from_frame = false;
#elif WASM_ENABLE_FAST_JIT != 0 #elif WASM_ENABLE_FAST_JIT != 0
fast_jit_call_func_bytecode(exec_env, function, frame); /* Only Fast JIT is enabled */
fast_jit_call_func_bytecode(module_inst, exec_env, function, frame);
#else #else
/* Both Fast JIT and LLVM JIT are disabled */
wasm_interp_call_func_bytecode(module_inst, exec_env, function, frame); wasm_interp_call_func_bytecode(module_inst, exec_env, function, frame);
#endif #endif
#else /* else of WASM_ENABLE_LAZY_JIT != 0 */
/* Fast JIT to LLVM JIT tier-up is enabled */
#if WASM_ENABLE_JIT != 0
/* LLVM JIT is enabled */
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 is enabled */
fast_jit_call_func_bytecode(module_inst, exec_env, function, frame);
#else
/* Both Fast JIT and LLVM JIT are disabled */
wasm_interp_call_func_bytecode(module_inst, exec_env, function, frame);
#endif
#endif /* end of WASM_ENABLE_LAZY_JIT != 0 */
(void)wasm_interp_call_func_bytecode; (void)wasm_interp_call_func_bytecode;
#if WASM_ENABLE_FAST_JIT != 0
(void)fast_jit_call_func_bytecode;
#endif
} }
/* Output the return value to the caller */ /* Output the return value to the caller */

View File

@ -428,6 +428,12 @@ destroy_wasm_type(WASMType *type)
return; return;
} }
#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
&& WASM_ENABLE_LAZY_JIT != 0
if (type->call_to_llvm_jit_from_fast_jit)
jit_code_cache_free(type->call_to_llvm_jit_from_fast_jit);
#endif
wasm_runtime_free(type); wasm_runtime_free(type);
} }
@ -2925,93 +2931,78 @@ calculate_global_data_offset(WASMModule *module)
module->global_data_size = data_offset; module->global_data_size = data_offset;
} }
#if WASM_ENABLE_JIT != 0 #if WASM_ENABLE_FAST_JIT != 0
static void *
orcjit_thread_callback(void *arg)
{
LLVMOrcJITTargetAddress func_addr = 0;
OrcJitThreadArg *thread_arg = (OrcJitThreadArg *)arg;
AOTCompContext *comp_ctx = thread_arg->comp_ctx;
WASMModule *module = thread_arg->module;
uint32 group_idx = thread_arg->group_idx;
uint32 group_stride = WASM_ORC_JIT_BACKEND_THREAD_NUM;
uint32 func_count = module->function_count;
uint32 i, j;
typedef void (*F)(void);
LLVMErrorRef error;
char func_name[48];
union {
F f;
void *v;
} u;
/* Compile jit functions of this group */
for (i = group_idx; i < func_count;
i += group_stride * WASM_ORC_JIT_COMPILE_THREAD_NUM) {
snprintf(func_name, sizeof(func_name), "%s%d%s", AOT_FUNC_PREFIX, i,
"_wrapper");
LOG_DEBUG("compile func %s", func_name);
error =
LLVMOrcLLLazyJITLookup(comp_ctx->orc_jit, &func_addr, func_name);
if (error != LLVMErrorSuccess) {
char *err_msg = LLVMGetErrorMessage(error);
os_printf("failed to compile orc jit function: %s", err_msg);
LLVMDisposeErrorMessage(err_msg);
continue;
}
/* Call the jit wrapper function to trigger its compilation, so as
to compile the actual jit functions, since we add the latter to
function list in the PartitionFunction callback */
u.v = (void *)func_addr;
u.f();
for (j = 0; j < WASM_ORC_JIT_COMPILE_THREAD_NUM; j++) {
if (i + j * group_stride < func_count)
module->func_ptrs_compiled[i + j * group_stride] = true;
}
if (module->orcjit_stop_compiling) {
break;
}
}
return NULL;
}
static void
orcjit_stop_compile_threads(WASMModule *module)
{
uint32 i, thread_num = (uint32)(sizeof(module->orcjit_thread_args)
/ sizeof(OrcJitThreadArg));
module->orcjit_stop_compiling = true;
for (i = 0; i < thread_num; i++) {
if (module->orcjit_threads[i])
os_thread_join(module->orcjit_threads[i], NULL);
}
}
static bool static bool
compile_llvm_jit_functions(WASMModule *module, char *error_buf, init_fast_jit_functions(WASMModule *module, char *error_buf,
uint32 error_buf_size) uint32 error_buf_size)
{
#if WASM_ENABLE_LAZY_JIT != 0
JitGlobals *jit_globals = jit_compiler_get_jit_globals();
#endif
uint32 i;
if (!module->function_count)
return true;
if (!(module->fast_jit_func_ptrs =
loader_malloc(sizeof(void *) * module->function_count, error_buf,
error_buf_size))) {
return false;
}
#if WASM_ENABLE_LAZY_JIT != 0
for (i = 0; i < module->function_count; i++) {
module->fast_jit_func_ptrs[i] =
jit_globals->compile_fast_jit_and_then_call;
}
#endif
for (i = 0; i < WASM_ORC_JIT_BACKEND_THREAD_NUM; i++) {
if (os_mutex_init(&module->fast_jit_thread_locks[i]) != 0) {
set_error_buf(error_buf, error_buf_size,
"init fast jit thread lock failed");
return false;
}
module->fast_jit_thread_locks_inited[i] = true;
}
return true;
}
#endif /* end of WASM_ENABLE_FAST_JIT != 0 */
#if WASM_ENABLE_JIT != 0
static bool
init_llvm_jit_functions_stage1(WASMModule *module, char *error_buf,
uint32 error_buf_size)
{ {
AOTCompOption option = { 0 }; AOTCompOption option = { 0 };
char *aot_last_error; char *aot_last_error;
uint64 size; uint64 size;
uint32 thread_num, i;
if (module->function_count > 0) { if (module->function_count == 0)
size = sizeof(void *) * (uint64)module->function_count return true;
+ sizeof(bool) * (uint64)module->function_count;
if (!(module->func_ptrs = #if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_LLVM_JIT != 0
loader_malloc(size, error_buf, error_buf_size))) { if (os_mutex_init(&module->tierup_wait_lock) != 0) {
return false; set_error_buf(error_buf, error_buf_size, "init jit tierup lock failed");
} return false;
module->func_ptrs_compiled =
(bool *)((uint8 *)module->func_ptrs
+ sizeof(void *) * module->function_count);
} }
if (os_cond_init(&module->tierup_wait_cond) != 0) {
set_error_buf(error_buf, error_buf_size, "init jit tierup cond failed");
os_mutex_destroy(&module->tierup_wait_lock);
return false;
}
module->tierup_wait_lock_inited = true;
#endif
size = sizeof(void *) * (uint64)module->function_count
+ sizeof(bool) * (uint64)module->function_count;
if (!(module->func_ptrs = loader_malloc(size, error_buf, error_buf_size))) {
return false;
}
module->func_ptrs_compiled =
(bool *)((uint8 *)module->func_ptrs
+ sizeof(void *) * module->function_count);
module->comp_data = aot_create_comp_data(module); module->comp_data = aot_create_comp_data(module);
if (!module->comp_data) { if (!module->comp_data) {
@ -3052,6 +3043,19 @@ compile_llvm_jit_functions(WASMModule *module, char *error_buf,
return false; return false;
} }
return true;
}
static bool
init_llvm_jit_functions_stage2(WASMModule *module, char *error_buf,
uint32 error_buf_size)
{
char *aot_last_error;
uint32 i;
if (module->function_count == 0)
return true;
if (!aot_compile_wasm(module->comp_ctx)) { if (!aot_compile_wasm(module->comp_ctx)) {
aot_last_error = aot_get_last_error(); aot_last_error = aot_get_last_error();
bh_assert(aot_last_error != NULL); bh_assert(aot_last_error != NULL);
@ -3059,7 +3063,7 @@ compile_llvm_jit_functions(WASMModule *module, char *error_buf,
return false; return false;
} }
bh_print_time("Begin to lookup jit functions"); bh_print_time("Begin to lookup llvm jit functions");
for (i = 0; i < module->function_count; i++) { for (i = 0; i < module->function_count; i++) {
LLVMOrcJITTargetAddress func_addr = 0; LLVMOrcJITTargetAddress func_addr = 0;
@ -3084,17 +3088,206 @@ compile_llvm_jit_functions(WASMModule *module, char *error_buf,
* loading/storing at the same time. * loading/storing at the same time.
*/ */
module->func_ptrs[i] = (void *)func_addr; module->func_ptrs[i] = (void *)func_addr;
module->functions[i]->llvm_jit_func_ptr = (void *)func_addr;
} }
bh_print_time("End lookup llvm jit functions");
return true;
}
#endif /* end of WASM_ENABLE_JIT != 0 */
#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
&& WASM_ENABLE_LAZY_JIT != 0
static void *
init_llvm_jit_functions_stage2_callback(void *arg)
{
WASMModule *module = (WASMModule *)arg;
char error_buf[128];
uint32 error_buf_size = (uint32)sizeof(error_buf);
if (!init_llvm_jit_functions_stage2(module, error_buf, error_buf_size)) {
module->orcjit_stop_compiling = true;
return NULL;
}
os_mutex_lock(&module->tierup_wait_lock);
module->llvm_jit_inited = true;
os_cond_broadcast(&module->tierup_wait_cond);
os_mutex_unlock(&module->tierup_wait_lock);
return NULL;
}
#endif
#if WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0
/* The callback function to compile jit functions */
static void *
orcjit_thread_callback(void *arg)
{
OrcJitThreadArg *thread_arg = (OrcJitThreadArg *)arg;
#if WASM_ENABLE_JIT != 0
AOTCompContext *comp_ctx = thread_arg->comp_ctx;
#endif
WASMModule *module = thread_arg->module;
uint32 group_idx = thread_arg->group_idx;
uint32 group_stride = WASM_ORC_JIT_BACKEND_THREAD_NUM;
uint32 func_count = module->function_count;
uint32 i;
#if WASM_ENABLE_FAST_JIT != 0
/* Compile fast jit funcitons of this group */
for (i = group_idx; i < func_count; i += group_stride) {
if (!jit_compiler_compile(module, i + module->import_function_count)) {
os_printf("failed to compile fast jit function %u\n", i);
break;
}
if (module->orcjit_stop_compiling) {
return NULL;
}
}
#endif
#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
&& WASM_ENABLE_LAZY_JIT != 0
/* For JIT tier-up, set each llvm jit func to call_to_fast_jit */
for (i = group_idx; i < func_count;
i += group_stride * WASM_ORC_JIT_COMPILE_THREAD_NUM) {
uint32 j;
for (j = 0; j < WASM_ORC_JIT_COMPILE_THREAD_NUM; j++) {
if (i + j * group_stride < func_count) {
if (!jit_compiler_set_call_to_fast_jit(
module,
i + j * group_stride + module->import_function_count)) {
os_printf(
"failed to compile call_to_fast_jit for func %u\n",
i + j * group_stride + module->import_function_count);
module->orcjit_stop_compiling = true;
return NULL;
}
}
if (module->orcjit_stop_compiling) {
return NULL;
}
}
}
/* Wait until init_llvm_jit_functions_stage2 finishes */
os_mutex_lock(&module->tierup_wait_lock);
while (!module->llvm_jit_inited) {
os_cond_reltimedwait(&module->tierup_wait_cond,
&module->tierup_wait_lock, 10);
if (module->orcjit_stop_compiling) {
/* init_llvm_jit_functions_stage2 failed */
os_mutex_unlock(&module->tierup_wait_lock);
return NULL;
}
}
os_mutex_unlock(&module->tierup_wait_lock);
#endif
#if WASM_ENABLE_JIT != 0
/* Compile llvm jit functions of this group */
for (i = group_idx; i < func_count;
i += group_stride * WASM_ORC_JIT_COMPILE_THREAD_NUM) {
LLVMOrcJITTargetAddress func_addr = 0;
LLVMErrorRef error;
char func_name[48];
typedef void (*F)(void);
union {
F f;
void *v;
} u;
uint32 j;
snprintf(func_name, sizeof(func_name), "%s%d%s", AOT_FUNC_PREFIX, i,
"_wrapper");
LOG_DEBUG("compile llvm jit func %s", func_name);
error =
LLVMOrcLLLazyJITLookup(comp_ctx->orc_jit, &func_addr, func_name);
if (error != LLVMErrorSuccess) {
char *err_msg = LLVMGetErrorMessage(error);
os_printf("failed to compile llvm jit function %u: %s", i, err_msg);
LLVMDisposeErrorMessage(err_msg);
break;
}
/* Call the jit wrapper function to trigger its compilation, so as
to compile the actual jit functions, since we add the latter to
function list in the PartitionFunction callback */
u.v = (void *)func_addr;
u.f();
for (j = 0; j < WASM_ORC_JIT_COMPILE_THREAD_NUM; j++) {
if (i + j * group_stride < func_count) {
module->func_ptrs_compiled[i + j * group_stride] = true;
#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_LAZY_JIT != 0
snprintf(func_name, sizeof(func_name), "%s%d", AOT_FUNC_PREFIX,
i + j * group_stride);
error = LLVMOrcLLLazyJITLookup(comp_ctx->orc_jit, &func_addr,
func_name);
if (error != LLVMErrorSuccess) {
char *err_msg = LLVMGetErrorMessage(error);
os_printf("failed to compile llvm jit function %u: %s", i,
err_msg);
LLVMDisposeErrorMessage(err_msg);
/* Ignore current llvm jit func, as its func ptr is
previous set to call_to_fast_jit, which also works */
continue;
}
jit_compiler_set_llvm_jit_func_ptr(
module,
i + j * group_stride + module->import_function_count,
(void *)func_addr);
/* Try to switch to call this llvm jit funtion instead of
fast jit function from fast jit jitted code */
jit_compiler_set_call_to_llvm_jit(
module,
i + j * group_stride + module->import_function_count);
#endif
}
}
if (module->orcjit_stop_compiling) {
break;
}
}
#endif
return NULL;
}
static void
orcjit_stop_compile_threads(WASMModule *module)
{
uint32 i, thread_num = (uint32)(sizeof(module->orcjit_thread_args)
/ sizeof(OrcJitThreadArg));
module->orcjit_stop_compiling = true;
for (i = 0; i < thread_num; i++) {
if (module->orcjit_threads[i])
os_thread_join(module->orcjit_threads[i], NULL);
}
}
static bool
compile_jit_functions(WASMModule *module, char *error_buf,
uint32 error_buf_size)
{
uint32 thread_num =
(uint32)(sizeof(module->orcjit_thread_args) / sizeof(OrcJitThreadArg));
uint32 i, j;
bh_print_time("Begin to compile jit functions"); bh_print_time("Begin to compile jit functions");
thread_num =
(uint32)(sizeof(module->orcjit_thread_args) / sizeof(OrcJitThreadArg));
/* Create threads to compile the jit functions */ /* Create threads to compile the jit functions */
for (i = 0; i < thread_num; i++) { for (i = 0; i < thread_num && i < module->function_count; i++) {
#if WASM_ENABLE_JIT != 0
module->orcjit_thread_args[i].comp_ctx = module->comp_ctx; module->orcjit_thread_args[i].comp_ctx = module->comp_ctx;
#endif
module->orcjit_thread_args[i].module = module; module->orcjit_thread_args[i].module = module;
module->orcjit_thread_args[i].group_idx = i; module->orcjit_thread_args[i].group_idx = i;
@ -3102,8 +3295,6 @@ compile_llvm_jit_functions(WASMModule *module, char *error_buf,
(void *)&module->orcjit_thread_args[i], (void *)&module->orcjit_thread_args[i],
APP_THREAD_STACK_SIZE_DEFAULT) APP_THREAD_STACK_SIZE_DEFAULT)
!= 0) { != 0) {
uint32 j;
set_error_buf(error_buf, error_buf_size, set_error_buf(error_buf, error_buf_size,
"create orcjit compile thread failed"); "create orcjit compile thread failed");
/* Terminate the threads created */ /* Terminate the threads created */
@ -3118,15 +3309,39 @@ compile_llvm_jit_functions(WASMModule *module, char *error_buf,
#if WASM_ENABLE_LAZY_JIT == 0 #if WASM_ENABLE_LAZY_JIT == 0
/* Wait until all jit functions are compiled for eager mode */ /* Wait until all jit functions are compiled for eager mode */
for (i = 0; i < thread_num; i++) { for (i = 0; i < thread_num; i++) {
os_thread_join(module->orcjit_threads[i], NULL); if (module->orcjit_threads[i])
os_thread_join(module->orcjit_threads[i], NULL);
}
#if WASM_ENABLE_FAST_JIT != 0
/* Ensure all the fast-jit functions are compiled */
for (i = 0; i < module->function_count; i++) {
if (!jit_compiler_is_compiled(module,
i + module->import_function_count)) {
set_error_buf(error_buf, error_buf_size,
"failed to compile fast jit function");
return false;
}
} }
#endif #endif
#if WASM_ENABLE_JIT != 0
/* Ensure all the llvm-jit functions are compiled */
for (i = 0; i < module->function_count; i++) {
if (!module->func_ptrs_compiled[i]) {
set_error_buf(error_buf, error_buf_size,
"failed to compile llvm jit function");
return false;
}
}
#endif
#endif /* end of WASM_ENABLE_LAZY_JIT == 0 */
bh_print_time("End compile jit functions"); bh_print_time("End compile jit functions");
return true; return true;
} }
#endif /* end of WASM_ENABLE_JIT != 0 */ #endif /* end of WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0 */
static bool static bool
wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func, wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func,
@ -3538,23 +3753,41 @@ load_from_sections(WASMModule *module, WASMSection *sections,
calculate_global_data_offset(module); calculate_global_data_offset(module);
#if WASM_ENABLE_FAST_JIT != 0 #if WASM_ENABLE_FAST_JIT != 0
if (module->function_count if (!init_fast_jit_functions(module, error_buf, error_buf_size)) {
&& !(module->fast_jit_func_ptrs =
loader_malloc(sizeof(void *) * module->function_count,
error_buf, error_buf_size))) {
return false;
}
if (!jit_compiler_compile_all(module)) {
set_error_buf(error_buf, error_buf_size, "fast jit compilation failed");
return false; return false;
} }
#endif #endif
#if WASM_ENABLE_JIT != 0 #if WASM_ENABLE_JIT != 0
if (!compile_llvm_jit_functions(module, error_buf, error_buf_size)) { if (!init_llvm_jit_functions_stage1(module, error_buf, error_buf_size)) {
return false; return false;
} }
#endif /* end of WASM_ENABLE_JIT != 0 */ #if !(WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_LAZY_JIT != 0)
if (!init_llvm_jit_functions_stage2(module, error_buf, error_buf_size)) {
return false;
}
#else
/* Run aot_compile_wasm in a backend thread, so as not to block the main
thread fast jit execution, since applying llvm optimizations in
aot_compile_wasm may cost a lot of time.
Create thread with enough native stack to apply llvm optimizations */
if (os_thread_create(&module->llvm_jit_init_thread,
init_llvm_jit_functions_stage2_callback,
(void *)module, APP_THREAD_STACK_SIZE_DEFAULT * 8)
!= 0) {
set_error_buf(error_buf, error_buf_size,
"create orcjit compile thread failed");
return false;
}
#endif
#endif
#if WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0
/* Create threads to compile the jit functions */
if (!compile_jit_functions(module, error_buf, error_buf_size)) {
return false;
}
#endif
#if WASM_ENABLE_MEMORY_TRACING != 0 #if WASM_ENABLE_MEMORY_TRACING != 0
wasm_runtime_dump_module_mem_consumption((WASMModuleCommon *)module); wasm_runtime_dump_module_mem_consumption((WASMModuleCommon *)module);
@ -3567,9 +3800,7 @@ create_module(char *error_buf, uint32 error_buf_size)
{ {
WASMModule *module = WASMModule *module =
loader_malloc(sizeof(WASMModule), error_buf, error_buf_size); loader_malloc(sizeof(WASMModule), error_buf, error_buf_size);
#if WASM_ENABLE_FAST_INTERP == 0
bh_list_status ret; bh_list_status ret;
#endif
if (!module) { if (!module) {
return NULL; return NULL;
@ -3584,19 +3815,31 @@ create_module(char *error_buf, uint32 error_buf_size)
module->br_table_cache_list = &module->br_table_cache_list_head; module->br_table_cache_list = &module->br_table_cache_list_head;
ret = bh_list_init(module->br_table_cache_list); ret = bh_list_init(module->br_table_cache_list);
bh_assert(ret == BH_LIST_SUCCESS); bh_assert(ret == BH_LIST_SUCCESS);
(void)ret;
#endif #endif
#if WASM_ENABLE_MULTI_MODULE != 0 #if WASM_ENABLE_MULTI_MODULE != 0
module->import_module_list = &module->import_module_list_head; module->import_module_list = &module->import_module_list_head;
ret = bh_list_init(module->import_module_list);
bh_assert(ret == BH_LIST_SUCCESS);
#endif #endif
#if WASM_ENABLE_DEBUG_INTERP != 0 #if WASM_ENABLE_DEBUG_INTERP != 0
bh_list_init(&module->fast_opcode_list); ret = bh_list_init(&module->fast_opcode_list);
if (os_mutex_init(&module->ref_count_lock) != 0) { bh_assert(ret == BH_LIST_SUCCESS);
#endif
#if WASM_ENABLE_DEBUG_INTERP != 0 \
|| (WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT \
&& WASM_ENABLE_LAZY_JIT != 0)
if (os_mutex_init(&module->instance_list_lock) != 0) {
set_error_buf(error_buf, error_buf_size,
"init instance list lock failed");
wasm_runtime_free(module); wasm_runtime_free(module);
return NULL; return NULL;
} }
#endif #endif
(void)ret;
return module; return module;
} }
@ -3964,10 +4207,19 @@ wasm_loader_unload(WASMModule *module)
if (!module) if (!module)
return; return;
#if WASM_ENABLE_JIT != 0 #if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT && WASM_ENABLE_LAZY_JIT != 0
/* Stop LLVM JIT compilation firstly to avoid accessing module->orcjit_stop_compiling = true;
if (module->llvm_jit_init_thread)
os_thread_join(module->llvm_jit_init_thread, NULL);
#endif
#if WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0
/* Stop Fast/LLVM JIT compilation firstly to avoid accessing
module internal data after they were freed */ module internal data after they were freed */
orcjit_stop_compile_threads(module); orcjit_stop_compile_threads(module);
#endif
#if WASM_ENABLE_JIT != 0
if (module->func_ptrs) if (module->func_ptrs)
wasm_runtime_free(module->func_ptrs); wasm_runtime_free(module->func_ptrs);
if (module->comp_ctx) if (module->comp_ctx)
@ -3976,6 +4228,13 @@ wasm_loader_unload(WASMModule *module)
aot_destroy_comp_data(module->comp_data); aot_destroy_comp_data(module->comp_data);
#endif #endif
#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT && WASM_ENABLE_LAZY_JIT != 0
if (module->tierup_wait_lock_inited) {
os_mutex_destroy(&module->tierup_wait_lock);
os_cond_destroy(&module->tierup_wait_cond);
}
#endif
if (module->types) { if (module->types) {
for (i = 0; i < module->type_count; i++) { for (i = 0; i < module->type_count; i++) {
if (module->types[i]) if (module->types[i])
@ -3997,6 +4256,18 @@ wasm_loader_unload(WASMModule *module)
wasm_runtime_free(module->functions[i]->code_compiled); wasm_runtime_free(module->functions[i]->code_compiled);
if (module->functions[i]->consts) if (module->functions[i]->consts)
wasm_runtime_free(module->functions[i]->consts); wasm_runtime_free(module->functions[i]->consts);
#endif
#if WASM_ENABLE_FAST_JIT != 0
if (module->functions[i]->fast_jit_jitted_code) {
jit_code_cache_free(
module->functions[i]->fast_jit_jitted_code);
}
#if WASM_ENABLE_JIT != 0 && WASM_ENABLE_LAZY_JIT != 0
if (module->functions[i]->llvm_jit_func_ptr) {
jit_code_cache_free(
module->functions[i]->llvm_jit_func_ptr);
}
#endif
#endif #endif
wasm_runtime_free(module->functions[i]); wasm_runtime_free(module->functions[i]);
} }
@ -4084,7 +4355,12 @@ wasm_loader_unload(WASMModule *module)
wasm_runtime_free(fast_opcode); wasm_runtime_free(fast_opcode);
fast_opcode = next; fast_opcode = next;
} }
os_mutex_destroy(&module->ref_count_lock); #endif
#if WASM_ENABLE_DEBUG_INTERP != 0 \
|| (WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT \
&& WASM_ENABLE_LAZY_JIT != 0)
os_mutex_destroy(&module->instance_list_lock);
#endif #endif
#if WASM_ENABLE_LOAD_CUSTOM_SECTION != 0 #if WASM_ENABLE_LOAD_CUSTOM_SECTION != 0
@ -4093,12 +4369,14 @@ wasm_loader_unload(WASMModule *module)
#if WASM_ENABLE_FAST_JIT != 0 #if WASM_ENABLE_FAST_JIT != 0
if (module->fast_jit_func_ptrs) { if (module->fast_jit_func_ptrs) {
for (i = 0; i < module->function_count; i++) {
if (module->fast_jit_func_ptrs[i])
jit_code_cache_free(module->fast_jit_func_ptrs[i]);
}
wasm_runtime_free(module->fast_jit_func_ptrs); wasm_runtime_free(module->fast_jit_func_ptrs);
} }
for (i = 0; i < WASM_ORC_JIT_BACKEND_THREAD_NUM; i++) {
if (module->fast_jit_thread_locks_inited[i]) {
os_mutex_destroy(&module->fast_jit_thread_locks[i]);
}
}
#endif #endif
wasm_runtime_free(module); wasm_runtime_free(module);

View File

@ -19,6 +19,9 @@
#if WASM_ENABLE_DEBUG_INTERP != 0 #if WASM_ENABLE_DEBUG_INTERP != 0
#include "../libraries/debug-engine/debug_engine.h" #include "../libraries/debug-engine/debug_engine.h"
#endif #endif
#if WASM_ENABLE_FAST_JIT != 0
#include "../fast-jit/jit_compiler.h"
#endif
#if WASM_ENABLE_JIT != 0 #if WASM_ENABLE_JIT != 0
#include "../aot/aot_runtime.h" #include "../aot/aot_runtime.h"
#endif #endif
@ -1414,30 +1417,10 @@ wasm_instantiate(WASMModule *module, bool is_sub_inst, uint32 stack_size,
extra_info_offset = (uint32)total_size; extra_info_offset = (uint32)total_size;
total_size += sizeof(WASMModuleInstanceExtra); total_size += sizeof(WASMModuleInstanceExtra);
#if WASM_ENABLE_DEBUG_INTERP != 0
if (!is_sub_inst) {
os_mutex_lock(&module->ref_count_lock);
if (module->ref_count != 0) {
LOG_WARNING(
"warning: multiple instances referencing the same module may "
"cause unexpected behaviour during debugging");
}
module->ref_count++;
os_mutex_unlock(&module->ref_count_lock);
}
#endif
/* Allocate the memory for module instance with memory instances, /* Allocate the memory for module instance with memory instances,
global data, table data appended at the end */ global data, table data appended at the end */
if (!(module_inst = if (!(module_inst =
runtime_malloc(total_size, error_buf, error_buf_size))) { runtime_malloc(total_size, error_buf, error_buf_size))) {
#if WASM_ENABLE_DEBUG_INTERP != 0
if (!is_sub_inst) {
os_mutex_lock(&module->ref_count_lock);
module->ref_count--;
os_mutex_unlock(&module->ref_count_lock);
}
#endif
return NULL; return NULL;
} }
@ -1827,6 +1810,33 @@ wasm_instantiate(WASMModule *module, bool is_sub_inst, uint32 stack_size,
} }
#endif #endif
#if WASM_ENABLE_DEBUG_INTERP != 0 \
|| (WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
&& WASM_ENABLE_LAZY_JIT != 0)
if (!is_sub_inst) {
/* Add module instance into module's instance list */
os_mutex_lock(&module->instance_list_lock);
#if WASM_ENABLE_DEBUG_INTERP != 0
if (module->instance_list) {
LOG_WARNING(
"warning: multiple instances referencing to the same module "
"may cause unexpected behaviour during debugging");
}
#endif
#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
&& WASM_ENABLE_LAZY_JIT != 0
/* Copy llvm func ptrs again in case that they were updated
after the module instance was created */
bh_memcpy_s(module_inst->func_ptrs + module->import_function_count,
sizeof(void *) * module->function_count, module->func_ptrs,
sizeof(void *) * module->function_count);
#endif
module_inst->e->next = module->instance_list;
module->instance_list = module_inst;
os_mutex_unlock(&module->instance_list_lock);
}
#endif
if (module->start_function != (uint32)-1) { if (module->start_function != (uint32)-1) {
/* TODO: fix start function can be import function issue */ /* TODO: fix start function can be import function issue */
if (module->start_function >= module->import_function_count) if (module->start_function >= module->import_function_count)
@ -1864,8 +1874,8 @@ wasm_instantiate(WASMModule *module, bool is_sub_inst, uint32 stack_size,
wasm_runtime_dump_module_inst_mem_consumption( wasm_runtime_dump_module_inst_mem_consumption(
(WASMModuleInstanceCommon *)module_inst); (WASMModuleInstanceCommon *)module_inst);
#endif #endif
(void)global_data_end;
(void)global_data_end;
return module_inst; return module_inst;
fail: fail:
@ -1935,11 +1945,28 @@ wasm_deinstantiate(WASMModuleInstance *module_inst, bool is_sub_inst)
} }
#endif #endif
#if WASM_ENABLE_DEBUG_INTERP != 0 #if WASM_ENABLE_DEBUG_INTERP != 0 \
|| (WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
&& WASM_ENABLE_LAZY_JIT != 0)
if (!is_sub_inst) { if (!is_sub_inst) {
os_mutex_lock(&module_inst->module->ref_count_lock); WASMModule *module = module_inst->module;
module_inst->module->ref_count--; WASMModuleInstance *instance_prev = NULL, *instance;
os_mutex_unlock(&module_inst->module->ref_count_lock); os_mutex_lock(&module->instance_list_lock);
instance = module->instance_list;
while (instance) {
if (instance == module_inst) {
if (!instance_prev)
module->instance_list = instance->e->next;
else
instance_prev->e->next = instance->e->next;
break;
}
instance_prev = instance;
instance = instance->e->next;
}
os_mutex_unlock(&module->instance_list_lock);
} }
#endif #endif
@ -2803,7 +2830,7 @@ fast_jit_call_indirect(WASMExecEnv *exec_env, uint32 tbl_idx, uint32 elem_idx,
return call_indirect(exec_env, tbl_idx, elem_idx, argc, argv, true, return call_indirect(exec_env, tbl_idx, elem_idx, argc, argv, true,
type_idx); type_idx);
} }
#endif #endif /* end of WASM_ENABLE_FAST_JIT != 0 */
#if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0 #if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0

View File

@ -59,7 +59,10 @@ typedef enum WASMExceptionID {
EXCE_AUX_STACK_UNDERFLOW, EXCE_AUX_STACK_UNDERFLOW,
EXCE_OUT_OF_BOUNDS_TABLE_ACCESS, EXCE_OUT_OF_BOUNDS_TABLE_ACCESS,
EXCE_OPERAND_STACK_OVERFLOW, EXCE_OPERAND_STACK_OVERFLOW,
#if WASM_ENABLE_FAST_JIT != 0
EXCE_FAILED_TO_COMPILE_FAST_JIT_FUNC,
EXCE_ALREADY_THROWN, EXCE_ALREADY_THROWN,
#endif
EXCE_NUM, EXCE_NUM,
} WASMExceptionID; } WASMExceptionID;
@ -221,6 +224,12 @@ typedef struct WASMModuleInstanceExtra {
#if WASM_ENABLE_MEMORY_PROFILING != 0 #if WASM_ENABLE_MEMORY_PROFILING != 0
uint32 max_aux_stack_used; uint32 max_aux_stack_used;
#endif #endif
#if WASM_ENABLE_DEBUG_INTERP != 0 \
|| (WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT \
&& WASM_ENABLE_LAZY_JIT != 0)
WASMModuleInstance *next;
#endif
} WASMModuleInstanceExtra; } WASMModuleInstanceExtra;
struct AOTFuncPerfProfInfo; struct AOTFuncPerfProfInfo;

View File

@ -240,7 +240,7 @@ make
By default in Linux, the `fast interpreter`, `AOT` and `Libc WASI` are enabled, and JIT is disabled. By default in Linux, the `fast interpreter`, `AOT` and `Libc 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. And the build target is set to X86_64 or X86_32 depending on the platform's bitwidth.
There are total 5 running modes supported: fast interpreter, classi interpreter, AOT, LLVM JIT and Fast JIT. There are total 6 running modes supported: fast interpreter, classi interpreter, AOT, LLVM JIT, Fast JIT and Multi-tier JIT.
(1) To run a wasm file with `fast interpreter` mode - build iwasm with default build and then: (1) To run a wasm file with `fast interpreter` mode - build iwasm with default build and then:
```Bash ```Bash
@ -301,6 +301,14 @@ make
``` ```
The Fast JIT is a lightweight JIT engine with quick startup, small footprint and good portability, and gains ~50% performance of AOT. The Fast JIT is a lightweight JIT engine with quick startup, small footprint and good portability, and gains ~50% performance of AOT.
(6) To enable the `Multi-tier JIT` mode:
``` Bash
mkdir build && cd build
cmake .. -DWAMR_BUILD_FAST_JTI=1 -DWAMR_BUILD_JIT=1
make
```
The Multi-tier JIT is a two level JIT tier-up engine, which launchs Fast JIT to run the wasm module as soon as possible and creates backend threads to compile the LLVM JIT functions at the same time, and when the LLVM JIT functions are compiled, the runtime will switch the extecution from the Fast JIT jitted code to LLVM JIT jitted code gradually, so as to gain the best performance.
Linux SGX (Intel Software Guard Extension) Linux SGX (Intel Software Guard Extension)
------------------------- -------------------------

View File

@ -16,7 +16,7 @@ function help()
echo "-c clean previous test results, not start test" echo "-c clean previous test results, not start test"
echo "-s {suite_name} test only one suite (spec)" echo "-s {suite_name} test only one suite (spec)"
echo "-m set compile target of iwasm(x86_64\x86_32\armv7_vfp\thumbv7_vfp\riscv64_lp64d\riscv64_lp64)" echo "-m set compile target of iwasm(x86_64\x86_32\armv7_vfp\thumbv7_vfp\riscv64_lp64d\riscv64_lp64)"
echo "-t set compile type of iwasm(classic-interp\fast-interp\jit\aot\fast-jit)" echo "-t set compile type of iwasm(classic-interp\fast-interp\jit\aot\fast-jit\multi-tier-jit)"
echo "-M enable multi module feature" echo "-M enable multi module feature"
echo "-p enable multi thread feature" echo "-p enable multi thread feature"
echo "-S enable SIMD feature" echo "-S enable SIMD feature"
@ -29,7 +29,7 @@ function help()
OPT_PARSED="" OPT_PARSED=""
WABT_BINARY_RELEASE="NO" WABT_BINARY_RELEASE="NO"
#default type #default type
TYPE=("classic-interp" "fast-interp" "jit" "aot" "fast-jit") TYPE=("classic-interp" "fast-interp" "jit" "aot" "fast-jit" "multi-tier-jit")
#default target #default target
TARGET="X86_64" TARGET="X86_64"
ENABLE_MULTI_MODULE=0 ENABLE_MULTI_MODULE=0
@ -80,7 +80,8 @@ do
t) t)
echo "set compile type of wamr " ${OPTARG} echo "set compile type of wamr " ${OPTARG}
if [[ ${OPTARG} != "classic-interp" && ${OPTARG} != "fast-interp" \ if [[ ${OPTARG} != "classic-interp" && ${OPTARG} != "fast-interp" \
&& ${OPTARG} != "jit" && ${OPTARG} != "aot" && ${OPTARG} != "fast-jit" ]]; then && ${OPTARG} != "jit" && ${OPTARG} != "aot"
&& ${OPTARG} != "fast-jit" && ${OPTARG} != "multi-tier-jit" ]]; then
echo "*----- please varify a type of compile when using -t! -----*" echo "*----- please varify a type of compile when using -t! -----*"
help help
exit 1 exit 1
@ -201,6 +202,12 @@ readonly FAST_JIT_COMPILE_FLAGS="\
-DWAMR_BUILD_FAST_JIT=1 \ -DWAMR_BUILD_FAST_JIT=1 \
-DWAMR_BUILD_SPEC_TEST=1" -DWAMR_BUILD_SPEC_TEST=1"
readonly MULTI_TIER_JIT_COMPILE_FLAGS="\
-DWAMR_BUILD_TARGET=${TARGET} \
-DWAMR_BUILD_INTERP=1 -DWAMR_BUILD_FAST_INTERP=0 \
-DWAMR_BUILD_FAST_JIT=1 -DWAMR_BUILD_JIT=1 \
-DWAMR_BUILD_SPEC_TEST=1"
readonly COMPILE_FLAGS=( readonly COMPILE_FLAGS=(
"${CLASSIC_INTERP_COMPILE_FLAGS}" "${CLASSIC_INTERP_COMPILE_FLAGS}"
"${FAST_INTERP_COMPILE_FLAGS}" "${FAST_INTERP_COMPILE_FLAGS}"
@ -208,6 +215,7 @@ readonly COMPILE_FLAGS=(
"${ORC_LAZY_JIT_COMPILE_FLAGS}" "${ORC_LAZY_JIT_COMPILE_FLAGS}"
"${AOT_COMPILE_FLAGS}" "${AOT_COMPILE_FLAGS}"
"${FAST_JIT_COMPILE_FLAGS}" "${FAST_JIT_COMPILE_FLAGS}"
"${MULTI_TIER_JIT_COMPILE_FLAGS}"
) )
# TODO: with libiwasm.so only # TODO: with libiwasm.so only
@ -397,6 +405,10 @@ function spec_test()
echo "fast-jit doesn't support multi-thread feature yet, skip it" echo "fast-jit doesn't support multi-thread feature yet, skip it"
return return
fi fi
if [[ $1 == 'multi-tier-jit' ]]; then
echo "multi-tier-jit doesn't support multi-thread feature yet, skip it"
return
fi
fi fi
if [[ ${ENABLE_XIP} == 1 ]]; then if [[ ${ENABLE_XIP} == 1 ]]; then
@ -641,7 +653,7 @@ function trigger()
"fast-jit") "fast-jit")
echo "work in fast-jit mode" echo "work in fast-jit mode"
# jit # fast-jit
BUILD_FLAGS="$FAST_JIT_COMPILE_FLAGS $EXTRA_COMPILE_FLAGS" BUILD_FLAGS="$FAST_JIT_COMPILE_FLAGS $EXTRA_COMPILE_FLAGS"
build_iwasm_with_cfg $BUILD_FLAGS build_iwasm_with_cfg $BUILD_FLAGS
for suite in "${TEST_CASE_ARR[@]}"; do for suite in "${TEST_CASE_ARR[@]}"; do
@ -649,6 +661,16 @@ function trigger()
done done
;; ;;
"multi-tier-jit")
echo "work in multi-tier-jit mode"
# multi-tier-jit
BUILD_FLAGS="$MULTI_TIER_JIT_COMPILE_FLAGS $EXTRA_COMPILE_FLAGS"
build_iwasm_with_cfg $BUILD_FLAGS
for suite in "${TEST_CASE_ARR[@]}"; do
$suite"_test" multi-tier-jit
done
;;
*) *)
echo "unexpected mode, do nothing" echo "unexpected mode, do nothing"
;; ;;