| From: rive | |
| Subject: [PATCH 0019] lean host callback crossing | |
| Two changes to what a call across the host boundary costs. | |
| AOT code reaches every import through aot_invoke_native, which always took | |
| the generic argument classifier. It now takes the quick dispatch from patch | |
| 0008 when the signature allows, as the fast interpreter already did. The | |
| kind is worked out once, where the import is resolved, so the call path only | |
| reads it and instances sharing a module never write to it. | |
| wasm_runtime_call_wasm_nested is an entry for a native that calls back into | |
| the module on the exec env and thread of the call that invoked it, such as a | |
| listener fired from inside a script call. That outer call already validated | |
| the exec env, set its thread info and published it on the instance, so the | |
| nested entry skips all three. Builds with hardware bound checks, AOT stack | |
| frames or multi module keep the ordinary entry, because those need the per | |
| call setup. | |
| diff --git a/core/iwasm/aot/aot_runtime.c b/core/iwasm/aot/aot_runtime.c | |
| --- a/core/iwasm/aot/aot_runtime.c | |
| +++ b/core/iwasm/aot/aot_runtime.c | |
| @@ -2529,6 +2529,32 @@ | |
| attachment, argv, argc, argv_ret); | |
| } | |
| #endif /* end of OS_ENABLE_HW_BOUND_CHECK */ | |
| + | |
| +bool | |
| +aot_call_function_nested(WASMExecEnv *exec_env, AOTFunctionInstance *function, | |
| + unsigned argc, uint32 argv[]) | |
| +{ | |
| +#if WASM_ENABLE_QUICK_AOT_ENTRY != 0 && !defined(OS_ENABLE_HW_BOUND_CHECK) \ | |
| + && WASM_ENABLE_AOT_STACK_FRAME == 0 && WASM_ENABLE_MULTI_MODULE == 0 | |
| + if (!function->is_import_func) { | |
| + AOTFuncType *func_type = function->u.func.func_type; | |
| + | |
| + /* the running call already validated the exec env, set its thread | |
| + info and published it on the instance */ | |
| + if (func_type->quick_aot_entry && func_type->result_count <= 1 | |
| + && argc >= func_type->param_cell_num) { | |
| + AOTModuleInstance *module_inst = | |
| + (AOTModuleInstance *)exec_env->module_inst; | |
| + void (*invoke)(void *func_ptr, void *exec_env, uint32 *argv, | |
| + uint32 *argv_ret) = func_type->quick_aot_entry; | |
| + | |
| + invoke(function->u.func.func_ptr, exec_env, argv, argv); | |
| + return !aot_copy_exception(module_inst, NULL); | |
| + } | |
| + } | |
| +#endif | |
| + return aot_call_function(exec_env, function, argc, argv); | |
| +} | |
| #ifdef AOT_STACK_FRAME_DEBUG | |
| typedef void (*stack_frame_callback_t)(struct WASMExecEnv *exec_env); | |
| @@ -3258,9 +3284,17 @@ | |
| } | |
| #endif | |
| #endif /* WASM_ENABLE_MULTI_MODULE != 0 */ | |
| - ret = | |
| - wasm_runtime_invoke_native(exec_env, func_ptr, func_type, signature, | |
| - attachment, argv, argc, argv); | |
| +#if WASM_ENABLE_QUICK_NATIVE != 0 | |
| + /* set when the import was resolved, so this path only reads */ | |
| + if (import_func->quick_call_kind > WASM_QUICK_NATIVE_NO) | |
| + ret = wasm_runtime_invoke_native_quick( | |
| + exec_env, func_ptr, func_type, import_func->quick_call_kind, | |
| + attachment, argv, argv); | |
| + else | |
| +#endif | |
| + ret = wasm_runtime_invoke_native(exec_env, func_ptr, func_type, | |
| + signature, attachment, argv, argc, | |
| + argv); | |
| #if WASM_ENABLE_MULTI_MODULE != 0 && WASM_ENABLE_AOT_STACK_FRAME != 0 | |
| /* Free all frames allocated, note that some frames | |
| may be allocated in AOT code and haven't been | |
| @@ -5634,6 +5668,12 @@ | |
| } | |
| } | |
| } | |
| +#endif | |
| +#if WASM_ENABLE_QUICK_NATIVE != 0 | |
| + if (import_func->func_ptr_linked && !import_func->call_conv_raw) | |
| + import_func->quick_call_kind = wasm_runtime_compute_quick_native_kind( | |
| + import_func->func_type, import_func->signature); | |
| #endif | |
| + | |
| return import_func->func_ptr_linked != NULL; | |
| } | |
| diff --git a/core/iwasm/aot/aot_runtime.h b/core/iwasm/aot/aot_runtime.h | |
| --- a/core/iwasm/aot/aot_runtime.h | |
| +++ b/core/iwasm/aot/aot_runtime.h | |
| @@ -632,6 +632,11 @@ | |
| aot_call_function(WASMExecEnv *exec_env, AOTFunctionInstance *function, | |
| unsigned argc, uint32 argv[]); | |
| +/* rive: see wasm_runtime_call_wasm_nested */ | |
| +bool | |
| +aot_call_function_nested(WASMExecEnv *exec_env, AOTFunctionInstance *function, | |
| + unsigned argc, uint32 argv[]); | |
| + | |
| /** | |
| * Set AOT module instance exception with exception string | |
| * | |
| diff --git a/core/iwasm/common/wasm_runtime_common.c b/core/iwasm/common/wasm_runtime_common.c | |
| --- a/core/iwasm/common/wasm_runtime_common.c | |
| +++ b/core/iwasm/common/wasm_runtime_common.c | |
| @@ -2718,6 +2718,24 @@ | |
| #endif | |
| return ret; | |
| +} | |
| + | |
| +bool | |
| +wasm_runtime_call_wasm_nested(WASMExecEnv *exec_env, | |
| + WASMFunctionInstanceCommon *function, | |
| + uint32 argc, uint32 argv[]) | |
| +{ | |
| +#if WASM_ENABLE_INTERP != 0 | |
| + if (exec_env->module_inst->module_type == Wasm_Module_Bytecode) | |
| + return wasm_call_function_nested( | |
| + exec_env, (WASMFunctionInstance *)function, argc, argv); | |
| +#endif | |
| +#if WASM_ENABLE_AOT != 0 | |
| + if (exec_env->module_inst->module_type == Wasm_Module_AoT) | |
| + return aot_call_function_nested( | |
| + exec_env, (AOTFunctionInstance *)function, argc, argv); | |
| +#endif | |
| + return false; | |
| } | |
| static void | |
| diff --git a/core/iwasm/compilation/aot.h b/core/iwasm/compilation/aot.h | |
| --- a/core/iwasm/compilation/aot.h | |
| +++ b/core/iwasm/compilation/aot.h | |
| @@ -199,6 +199,9 @@ | |
| bool call_conv_raw; | |
| bool call_conv_wasm_c_api; | |
| bool wasm_c_api_with_env; | |
| + /* rive: quick host-call kind, set when the import resolves, see | |
| + wasm_runtime_common.h */ | |
| + uint8 quick_call_kind; | |
| } AOTImportFunc; | |
| /** | |
| diff --git a/core/iwasm/include/wasm_export.h b/core/iwasm/include/wasm_export.h | |
| --- a/core/iwasm/include/wasm_export.h | |
| +++ b/core/iwasm/include/wasm_export.h | |
| @@ -1165,6 +1165,16 @@ | |
| WASM_RUNTIME_API_EXTERN bool | |
| wasm_runtime_call_wasm(wasm_exec_env_t exec_env, wasm_function_inst_t function, | |
| uint32_t argc, uint32_t argv[]); | |
| + | |
| +/** | |
| + * rive: wasm_runtime_call_wasm for a native re-entering the module on the | |
| + * exec env and thread of the call that invoked it, which already validated | |
| + * the exec env and set its thread info. No reference type arguments. | |
| + */ | |
| +WASM_RUNTIME_API_EXTERN bool | |
| +wasm_runtime_call_wasm_nested(wasm_exec_env_t exec_env, | |
| + wasm_function_inst_t function, uint32_t argc, | |
| + uint32_t argv[]); | |
| /** | |
| * Call the given WASM function of a WASM module instance with | |
| diff --git a/core/iwasm/interpreter/wasm_runtime.c b/core/iwasm/interpreter/wasm_runtime.c | |
| --- a/core/iwasm/interpreter/wasm_runtime.c | |
| +++ b/core/iwasm/interpreter/wasm_runtime.c | |
| @@ -3690,6 +3690,21 @@ | |
| return !wasm_copy_exception(module_inst, NULL); | |
| } | |
| +bool | |
| +wasm_call_function_nested(WASMExecEnv *exec_env, WASMFunctionInstance *function, | |
| + unsigned argc, uint32 argv[]) | |
| +{ | |
| +#ifndef OS_ENABLE_HW_BOUND_CHECK | |
| + WASMModuleInstance *module_inst = | |
| + (WASMModuleInstance *)exec_env->module_inst; | |
| + | |
| + wasm_interp_call_wasm(module_inst, exec_env, function, argc, argv); | |
| + return !wasm_copy_exception(module_inst, NULL); | |
| +#else | |
| + return wasm_call_function(exec_env, function, argc, argv); | |
| +#endif | |
| +} | |
| + | |
| #if WASM_ENABLE_PERF_PROFILING != 0 || WASM_ENABLE_DUMP_CALL_STACK != 0 | |
| /* look for the function name */ | |
| static char * | |
| diff --git a/core/iwasm/interpreter/wasm_runtime.h b/core/iwasm/interpreter/wasm_runtime.h | |
| --- a/core/iwasm/interpreter/wasm_runtime.h | |
| +++ b/core/iwasm/interpreter/wasm_runtime.h | |
| @@ -599,6 +599,11 @@ | |
| wasm_call_function(WASMExecEnv *exec_env, WASMFunctionInstance *function, | |
| unsigned argc, uint32 argv[]); | |
| +/* rive: see wasm_runtime_call_wasm_nested */ | |
| +bool | |
| +wasm_call_function_nested(WASMExecEnv *exec_env, WASMFunctionInstance *function, | |
| + unsigned argc, uint32 argv[]); | |
| + | |
| void | |
| wasm_set_exception(WASMModuleInstance *module, const char *exception); | |