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
20 changed files with 1775 additions and 221 deletions

View File

@ -10,9 +10,9 @@
#include "../interpreter/wasm.h"
typedef struct JitCompilerPass {
/* Name of the pass. */
/* Name of the pass */
const char *name;
/* The entry of the compiler pass. */
/* The entry of the compiler pass */
bool (*run)(JitCompContext *cc);
} JitCompilerPass;
@ -30,7 +30,7 @@ static JitCompilerPass compiler_passes[] = {
#undef REG_PASS
};
/* Number of compiler passes. */
/* Number of compiler passes */
#define COMPILER_PASS_NUM (sizeof(compiler_passes) / sizeof(compiler_passes[0]))
#if WASM_ENABLE_FAST_JIT_DUMP == 0
@ -43,14 +43,17 @@ static const uint8 compiler_passes_with_dump[] = {
};
#endif
/* The exported global data of JIT compiler. */
/* The exported global data of JIT compiler */
static JitGlobals jit_globals = {
#if WASM_ENABLE_FAST_JIT_DUMP == 0
.passes = compiler_passes_without_dump,
#else
.passes = compiler_passes_with_dump,
#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 */
@ -60,7 +63,7 @@ apply_compiler_passes(JitCompContext *cc)
const uint8 *p = jit_globals.passes;
for (; *p; p++) {
/* Set the pass NO. */
/* Set the pass NO */
cc->cur_pass_no = p - jit_globals.passes;
bh_assert(*p < COMPILER_PASS_NUM);
@ -120,37 +123,53 @@ jit_compiler_get_pass_name(unsigned i)
bool
jit_compiler_compile(WASMModule *module, uint32 func_idx)
{
JitCompContext *cc;
JitCompContext *cc = NULL;
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. */
if (!(cc = jit_calloc(sizeof(*cc))))
return false;
/* Lock to avoid duplicated compilation by other threads */
os_mutex_lock(&module->fast_jit_thread_locks[j]);
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)) {
jit_free(cc);
return false;
goto fail;
}
cc->cur_wasm_module = module;
cc->cur_wasm_func =
module->functions[func_idx - module->import_function_count];
cc->cur_wasm_func = module->functions[i];
cc->cur_wasm_func_idx = func_idx;
cc->mem_space_unchanged = (!cc->cur_wasm_func->has_op_memory_grow
&& !cc->cur_wasm_func->has_op_func_call)
|| (!module->possible_memory_grow);
/* Apply compiler passes. */
/* Apply compiler passes */
if (!apply_compiler_passes(cc) || jit_get_last_error(cc)) {
last_error = jit_get_last_error(cc);
os_printf("fast jit compilation failed: %s\n",
last_error ? last_error : "unknown error");
ret = false;
goto fail;
}
/* Delete the compilation context. */
jit_cc_delete(cc);
ret = true;
fail:
/* Destroy the compilation context */
if (cc)
jit_cc_delete(cc);
os_mutex_unlock(&module->fast_jit_thread_locks[j]);
return ret;
}
@ -169,8 +188,92 @@ jit_compiler_compile_all(WASMModule *module)
return true;
}
int
jit_interp_switch_to_jitted(void *exec_env, JitInterpSwitchInfo *info, void *pc)
bool
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);
}