blob: 7cafd37a563692e152ac5a7b92b8f54a28543010 [file] [edit]
diff --git a/core/iwasm/common/wasm_runtime_common.c b/core/iwasm/common/wasm_runtime_common.c
index 943b46f..5853813 100644
--- a/core/iwasm/common/wasm_runtime_common.c
+++ b/core/iwasm/common/wasm_runtime_common.c
@@ -6234,6 +6234,142 @@ fail:
|| defined(BUILD_TARGET_RISCV64_LP64D) \
|| defined(BUILD_TARGET_RISCV64_LP64) */
+#if WASM_ENABLE_QUICK_NATIVE != 0
+
+uint8
+wasm_runtime_compute_quick_native_kind(const WASMFuncType *func_type,
+ const char *signature)
+{
+ uint32 i, n_int = 0, n_fp = 0;
+
+ /* any conversion marker in the signature needs the generic path */
+ if (signature) {
+ const char *s = signature;
+ for (; *s; s++)
+ if (*s != '(' && *s != ')' && *s != 'i' && *s != 'I' && *s != 'f'
+ && *s != 'F')
+ return WASM_QUICK_NATIVE_NO;
+ }
+
+ if (func_type->result_count > 1)
+ return WASM_QUICK_NATIVE_NO;
+
+ for (i = 0; i < func_type->param_count; i++) {
+ switch (func_type->types[i]) {
+ case VALUE_TYPE_I32:
+ case VALUE_TYPE_I64:
+ if (++n_int > 4)
+ return WASM_QUICK_NATIVE_NO;
+ break;
+ case VALUE_TYPE_F32:
+ case VALUE_TYPE_F64:
+ if (++n_fp > 8)
+ return WASM_QUICK_NATIVE_NO;
+ break;
+ default:
+ return WASM_QUICK_NATIVE_NO;
+ }
+ }
+
+ if (func_type->result_count == 0)
+ return WASM_QUICK_NATIVE_RET_VOID;
+ switch (func_type->types[func_type->param_count]) {
+ case VALUE_TYPE_I32:
+ return WASM_QUICK_NATIVE_RET_I32;
+ case VALUE_TYPE_I64:
+ return WASM_QUICK_NATIVE_RET_I64;
+ case VALUE_TYPE_F32:
+ return WASM_QUICK_NATIVE_RET_F32;
+ case VALUE_TYPE_F64:
+ return WASM_QUICK_NATIVE_RET_F64;
+ default:
+ return WASM_QUICK_NATIVE_NO;
+ }
+}
+
+/* the shared arg shape: callees read their int args from the int registers
+ and float args from the float registers, extra registers are ignored */
+typedef uint64 (*quick_native_i_t)(WASMExecEnv *, uint64, uint64, uint64,
+ uint64, double, double, double, double,
+ double, double, double, double);
+typedef float32 (*quick_native_f32_t)(WASMExecEnv *, uint64, uint64, uint64,
+ uint64, double, double, double, double,
+ double, double, double, double);
+typedef float64 (*quick_native_f64_t)(WASMExecEnv *, uint64, uint64, uint64,
+ uint64, double, double, double, double,
+ double, double, double, double);
+
+#define QUICK_NATIVE_ARGS \
+ exec_env, ints[0], ints[1], ints[2], ints[3], fps[0], fps[1], fps[2], \
+ fps[3], fps[4], fps[5], fps[6], fps[7]
+
+bool
+wasm_runtime_invoke_native_quick(WASMExecEnv *exec_env, void *func_ptr,
+ const WASMFuncType *func_type, uint8 ret_kind,
+ void *attachment, uint32 *argv,
+ uint32 *argv_ret)
+{
+ WASMModuleInstanceCommon *module = wasm_runtime_get_module_inst(exec_env);
+ uint64 ints[4] = { 0 };
+ double fps[8] = { 0 };
+ union {
+ uint64 u;
+ double d;
+ } fbits;
+ uint32 n_int = 0, n_fp = 0, i;
+ uint32 *p = argv;
+
+ for (i = 0; i < func_type->param_count; i++) {
+ switch (func_type->types[i]) {
+ case VALUE_TYPE_I32:
+ ints[n_int++] = *p++;
+ break;
+ case VALUE_TYPE_I64:
+ ints[n_int++] = (uint64)GET_I64_FROM_ADDR(p);
+ p += 2;
+ break;
+ case VALUE_TYPE_F32:
+ /* f32 args travel as the low half of a double register */
+ fbits.u = *p++;
+ fps[n_fp++] = fbits.d;
+ break;
+ default: /* VALUE_TYPE_F64 */
+ fbits.u = (uint64)GET_I64_FROM_ADDR(p);
+ fps[n_fp++] = fbits.d;
+ p += 2;
+ break;
+ }
+ }
+
+ exec_env->attachment = attachment;
+ switch (ret_kind) {
+ case WASM_QUICK_NATIVE_RET_VOID:
+ ((quick_native_i_t)func_ptr)(QUICK_NATIVE_ARGS);
+ break;
+ case WASM_QUICK_NATIVE_RET_I32:
+ argv_ret[0] =
+ (uint32)((quick_native_i_t)func_ptr)(QUICK_NATIVE_ARGS);
+ break;
+ case WASM_QUICK_NATIVE_RET_I64:
+ PUT_I64_TO_ADDR(argv_ret, (int64)((quick_native_i_t)func_ptr)(
+ QUICK_NATIVE_ARGS));
+ break;
+ case WASM_QUICK_NATIVE_RET_F32:
+ *(float32 *)argv_ret =
+ ((quick_native_f32_t)func_ptr)(QUICK_NATIVE_ARGS);
+ break;
+ default: /* WASM_QUICK_NATIVE_RET_F64 */
+ PUT_F64_TO_ADDR(argv_ret,
+ ((quick_native_f64_t)func_ptr)(QUICK_NATIVE_ARGS));
+ break;
+ }
+ exec_env->attachment = NULL;
+
+ return !wasm_runtime_copy_exception(module, NULL);
+}
+
+#endif /* end of WASM_ENABLE_QUICK_NATIVE */
+
bool
wasm_runtime_call_indirect(WASMExecEnv *exec_env, uint32 element_index,
uint32 argc, uint32 argv[])
diff --git a/core/iwasm/common/wasm_runtime_common.h b/core/iwasm/common/wasm_runtime_common.h
index 324620b..285ac40 100644
--- a/core/iwasm/common/wasm_runtime_common.h
+++ b/core/iwasm/common/wasm_runtime_common.h
@@ -1255,6 +1255,41 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
void *attachment, uint32 *argv, uint32 argc,
uint32 *ret);
+/* rive: direct host-call dispatch for simple signatures skips the generic
+ arg classifier; relies on int and float args living in disjoint register
+ files, which Windows x64 does not honor */
+#ifndef WASM_ENABLE_QUICK_NATIVE
+#if !defined(_WIN32) && !defined(_WIN32_) \
+ && (defined(BUILD_TARGET_AARCH64) || defined(BUILD_TARGET_X86_64) \
+ || defined(BUILD_TARGET_AMD_64))
+#define WASM_ENABLE_QUICK_NATIVE 1
+#else
+#define WASM_ENABLE_QUICK_NATIVE 0
+#endif
+#endif
+
+#if WASM_ENABLE_QUICK_NATIVE != 0
+enum {
+ WASM_QUICK_NATIVE_UNKNOWN = 0,
+ WASM_QUICK_NATIVE_NO = 1,
+ WASM_QUICK_NATIVE_RET_VOID = 2,
+ WASM_QUICK_NATIVE_RET_I32 = 3,
+ WASM_QUICK_NATIVE_RET_I64 = 4,
+ WASM_QUICK_NATIVE_RET_F32 = 5,
+ WASM_QUICK_NATIVE_RET_F64 = 6,
+};
+
+uint8
+wasm_runtime_compute_quick_native_kind(const WASMFuncType *func_type,
+ const char *signature);
+
+bool
+wasm_runtime_invoke_native_quick(WASMExecEnv *exec_env, void *func_ptr,
+ const WASMFuncType *func_type, uint8 ret_kind,
+ void *attachment, uint32 *argv,
+ uint32 *argv_ret);
+#endif
+
bool
wasm_runtime_invoke_native_raw(WASMExecEnv *exec_env, void *func_ptr,
const WASMFuncType *func_type,
diff --git a/core/iwasm/interpreter/wasm.h b/core/iwasm/interpreter/wasm.h
index 0dd7395..380890c 100644
--- a/core/iwasm/interpreter/wasm.h
+++ b/core/iwasm/interpreter/wasm.h
@@ -613,6 +613,8 @@ typedef struct WASMFunctionImport {
#endif
bool call_conv_raw;
bool call_conv_wasm_c_api;
+ /* rive: lazily computed quick host-call kind, see wasm_runtime_common.h */
+ uint8 quick_call_kind;
#if WASM_ENABLE_MULTI_MODULE != 0
WASMModule *import_module;
WASMFunction *import_func_linked;
diff --git a/core/iwasm/interpreter/wasm_interp_fast.c b/core/iwasm/interpreter/wasm_interp_fast.c
index c2aebd3..ddaf564 100644
--- a/core/iwasm/interpreter/wasm_interp_fast.c
+++ b/core/iwasm/interpreter/wasm_interp_fast.c
@@ -1375,10 +1375,24 @@ wasm_interp_call_func_native(WASMModuleInstance *module_inst,
}
}
else if (!func_import->call_conv_raw) {
- ret = wasm_runtime_invoke_native(
- exec_env, native_func_pointer, func_import->func_type,
- func_import->signature, func_import->attachment, frame->lp,
- cur_func->param_cell_num, argv_ret);
+#if WASM_ENABLE_QUICK_NATIVE != 0
+ uint8 quick_kind = func_import->quick_call_kind;
+ if (quick_kind == WASM_QUICK_NATIVE_UNKNOWN) {
+ /* benign race: concurrent recompute stores the same value */
+ quick_kind = wasm_runtime_compute_quick_native_kind(
+ func_import->func_type, func_import->signature);
+ func_import->quick_call_kind = quick_kind;
+ }
+ if (quick_kind != WASM_QUICK_NATIVE_NO)
+ ret = wasm_runtime_invoke_native_quick(
+ exec_env, native_func_pointer, func_import->func_type,
+ quick_kind, func_import->attachment, frame->lp, argv_ret);
+ else
+#endif
+ ret = wasm_runtime_invoke_native(
+ exec_env, native_func_pointer, func_import->func_type,
+ func_import->signature, func_import->attachment, frame->lp,
+ cur_func->param_cell_num, argv_ret);
}
else {
ret = wasm_runtime_invoke_native_raw(