Register quick call entries to speedup the aot/jit func call process (#2978)

In some scenarios there may be lots of callings to AOT/JIT functions from the
host embedder, which expects good performance for the calling process, while
in the current implementation, runtime calls the wasm_runtime_invoke_native
to prepare the array of registers and stacks for the invokeNative assemble code,
and the latter then puts the elements in the array to physical registers and
native stacks and calls the AOT/JIT function, there may be many data copying
and handlings which impact the performance.

This PR registers some quick AOT/JIT entries for some simple wasm signatures,
and let runtime call the entry to directly invoke the AOT/JIT function instead of
calling wasm_runtime_invoke_native, which speedups the calling process.

We may extend the mechanism next to allow the developer to register his quick
AOT/JIT entries to speedup the calling process of invoking the AOT/JIT functions
for some specific signatures.
This commit is contained in:
Wenyong Huang 2024-01-10 16:44:09 +08:00 committed by GitHub
parent 6fa6d6d9a5
commit 7c7684819d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 1044 additions and 143 deletions

View File

@ -449,7 +449,18 @@ if (WAMR_CONFIGUABLE_BOUNDS_CHECKS EQUAL 1)
endif ()
if (WAMR_BUILD_LINUX_PERF EQUAL 1)
add_definitions (-DWASM_ENABLE_LINUX_PERF=1)
message (" Enable linux perf support")
message (" Linux perf support enabled")
endif ()
if (NOT DEFINED WAMR_BUILD_QUICK_AOT_ENTRY)
# Enable quick aot/jit entries by default
set (WAMR_BUILD_QUICK_AOT_ENTRY 1)
endif ()
if (WAMR_BUILD_QUICK_AOT_ENTRY EQUAL 1)
add_definitions (-DWASM_ENABLE_QUICK_AOT_ENTRY=1)
message (" Quick AOT/JIT entries enabled")
else ()
add_definitions (-DWASM_ENABLE_QUICK_AOT_ENTRY=0)
message (" Quick AOT/JIT entries disabled")
endif ()
if (APPLE)

View File

@ -495,4 +495,11 @@
#define WASM_ENABLE_LINUX_PERF 0
#endif
/* Support registering quick AOT/JIT function entries of some func types
to speedup the calling process of invoking the AOT/JIT functions of
these types from the host embedder */
#ifndef WASM_ENABLE_QUICK_AOT_ENTRY
#define WASM_ENABLE_QUICK_AOT_ENTRY 1
#endif
#endif /* end of _CONFIG_H_ */

View File

@ -1202,6 +1202,11 @@ load_func_types(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
func_types[i]->param_cell_num = (uint16)param_cell_num;
func_types[i]->ret_cell_num = (uint16)ret_cell_num;
#if WASM_ENABLE_QUICK_AOT_ENTRY != 0
func_types[i]->quick_aot_entry =
wasm_native_lookup_quick_aot_entry(func_types[i]);
#endif
}
*p_buf = buf;

View File

@ -1385,9 +1385,6 @@ invoke_native_with_hw_bound_check(WASMExecEnv *exec_env, void *func_ptr,
WASMJmpBuf jmpbuf_node = { 0 }, *jmpbuf_node_pop;
uint32 page_size = os_getpagesize();
uint32 guard_page_count = STACK_OVERFLOW_CHECK_GUARD_PAGE_COUNT;
uint16 param_count = func_type->param_count;
uint16 result_count = func_type->result_count;
const uint8 *types = func_type->types;
#ifdef BH_PLATFORM_WINDOWS
int result;
bool has_exception;
@ -1426,28 +1423,22 @@ invoke_native_with_hw_bound_check(WASMExecEnv *exec_env, void *func_ptr,
wasm_exec_env_push_jmpbuf(exec_env, &jmpbuf_node);
if (os_setjmp(jmpbuf_node.jmpbuf) == 0) {
/* Quick call with func_ptr if the function signature is simple */
if (!signature && param_count == 1 && types[0] == VALUE_TYPE_I32) {
if (result_count == 0) {
void (*NativeFunc)(WASMExecEnv *, uint32) =
(void (*)(WASMExecEnv *, uint32))func_ptr;
NativeFunc(exec_env, argv[0]);
ret = aot_copy_exception(module_inst, NULL) ? false : true;
}
else if (result_count == 1
&& types[param_count] == VALUE_TYPE_I32) {
uint32 (*NativeFunc)(WASMExecEnv *, uint32) =
(uint32(*)(WASMExecEnv *, uint32))func_ptr;
argv_ret[0] = NativeFunc(exec_env, argv[0]);
ret = aot_copy_exception(module_inst, NULL) ? false : true;
}
else {
ret = wasm_runtime_invoke_native(exec_env, func_ptr, func_type,
signature, attachment, argv,
argc, argv_ret);
}
#if WASM_ENABLE_QUICK_AOT_ENTRY != 0
/* Quick call if the quick aot entry is registered */
if (!signature && func_type->quick_aot_entry) {
void (*invoke_native)(
void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
uint32 *argv_ret) = func_type->quick_aot_entry;
invoke_native(func_ptr,
func_type->result_count > 0
? func_type->types[func_type->param_count]
: VALUE_TYPE_VOID,
exec_env, argv, argv_ret);
ret = !aot_copy_exception(module_inst, NULL);
}
else {
else
#endif
{
ret = wasm_runtime_invoke_native(exec_env, func_ptr, func_type,
signature, attachment, argv, argc,
argv_ret);

File diff suppressed because it is too large Load Diff

View File

@ -104,6 +104,11 @@ wasm_native_init();
void
wasm_native_destroy();
#if WASM_ENABLE_QUICK_AOT_ENTRY != 0
void *
wasm_native_lookup_quick_aot_entry(const WASMType *func_type);
#endif
#ifdef __cplusplus
}
#endif

View File

@ -129,6 +129,10 @@ typedef struct WASMType {
/* 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
#if WASM_ENABLE_QUICK_AOT_ENTRY != 0
/* Quick AOT/JIT entry of this func type */
void *quick_aot_entry;
#endif
/* types of params and results */
uint8 types[1];

View File

@ -4199,12 +4199,29 @@ llvm_jit_call_func_bytecode(WASMModuleInstance *module_inst,
ret = true;
}
else {
ret = wasm_runtime_invoke_native(
exec_env, module_inst->func_ptrs[func_idx], func_type, NULL, NULL,
argv, argc, argv);
if (ret)
#if WASM_ENABLE_QUICK_AOT_ENTRY != 0
/* Quick call if the quick jit entry is registered */
if (func_type->quick_aot_entry) {
void (*invoke_native)(
void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
uint32 *argv_ret) = func_type->quick_aot_entry;
invoke_native(module_inst->func_ptrs[func_idx],
func_type->result_count > 0
? func_type->types[func_type->param_count]
: VALUE_TYPE_VOID,
exec_env, argv, argv);
ret = !wasm_copy_exception(module_inst, NULL);
}
else
#endif
{
ret = wasm_runtime_invoke_native(
exec_env, module_inst->func_ptrs[func_idx], func_type, NULL,
NULL, argv, argc, argv);
if (ret)
ret = !wasm_copy_exception(module_inst, NULL);
}
}
fail:

View File

@ -641,6 +641,10 @@ load_type_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
type->param_cell_num = (uint16)param_cell_num;
type->ret_cell_num = (uint16)ret_cell_num;
#if WASM_ENABLE_QUICK_AOT_ENTRY != 0
type->quick_aot_entry = wasm_native_lookup_quick_aot_entry(type);
#endif
/* If there is already a same type created, use it instead */
for (j = 0; j < i; j++) {
if (wasm_type_equal(type, module->types[j])) {

View File

@ -418,6 +418,10 @@ load_type_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
type->param_cell_num = (uint16)param_cell_num;
type->ret_cell_num = (uint16)ret_cell_num;
#if WASM_ENABLE_QUICK_AOT_ENTRY != 0
type->quick_aot_entry = wasm_native_lookup_quick_aot_entry(type);
#endif
/* If there is already a same type created, use it instead */
for (j = 0; j < i; ++j) {
if (wasm_type_equal(type, module->types[j])) {