mirror of
https://github.com/bytecodealliance/wasm-micro-runtime.git
synced 2025-02-06 23:15:16 +00:00
7c7684819d
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.
1551 lines
49 KiB
C
1551 lines
49 KiB
C
/*
|
|
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
|
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
*/
|
|
|
|
#include "wasm_native.h"
|
|
#include "wasm_runtime_common.h"
|
|
#include "bh_log.h"
|
|
#if WASM_ENABLE_INTERP != 0
|
|
#include "../interpreter/wasm_runtime.h"
|
|
#endif
|
|
#if WASM_ENABLE_AOT != 0
|
|
#include "../aot/aot_runtime.h"
|
|
#endif
|
|
#if WASM_ENABLE_THREAD_MGR != 0
|
|
#include "../libraries/thread-mgr/thread_manager.h"
|
|
#endif
|
|
|
|
static NativeSymbolsList g_native_symbols_list = NULL;
|
|
|
|
#if WASM_ENABLE_LIBC_WASI != 0
|
|
static void *g_wasi_context_key;
|
|
#endif /* WASM_ENABLE_LIBC_WASI */
|
|
|
|
uint32
|
|
get_libc_builtin_export_apis(NativeSymbol **p_libc_builtin_apis);
|
|
|
|
#if WASM_ENABLE_SPEC_TEST != 0
|
|
uint32
|
|
get_spectest_export_apis(NativeSymbol **p_libc_builtin_apis);
|
|
#endif
|
|
|
|
uint32
|
|
get_libc_wasi_export_apis(NativeSymbol **p_libc_wasi_apis);
|
|
|
|
uint32_t
|
|
get_wasi_nn_export_apis(NativeSymbol **p_libc_wasi_apis);
|
|
|
|
uint32
|
|
get_base_lib_export_apis(NativeSymbol **p_base_lib_apis);
|
|
|
|
uint32
|
|
get_ext_lib_export_apis(NativeSymbol **p_ext_lib_apis);
|
|
|
|
#if WASM_ENABLE_LIB_PTHREAD != 0
|
|
bool
|
|
lib_pthread_init();
|
|
|
|
void
|
|
lib_pthread_destroy();
|
|
|
|
uint32
|
|
get_lib_pthread_export_apis(NativeSymbol **p_lib_pthread_apis);
|
|
#endif
|
|
|
|
#if WASM_ENABLE_LIB_WASI_THREADS != 0
|
|
bool
|
|
lib_wasi_threads_init(void);
|
|
|
|
void
|
|
lib_wasi_threads_destroy(void);
|
|
|
|
uint32
|
|
get_lib_wasi_threads_export_apis(NativeSymbol **p_lib_wasi_threads_apis);
|
|
#endif
|
|
|
|
uint32
|
|
get_libc_emcc_export_apis(NativeSymbol **p_libc_emcc_apis);
|
|
|
|
uint32
|
|
get_lib_rats_export_apis(NativeSymbol **p_lib_rats_apis);
|
|
|
|
static bool
|
|
compare_type_with_signautre(uint8 type, const char signature)
|
|
{
|
|
const char num_sig_map[] = { 'F', 'f', 'I', 'i' };
|
|
|
|
if (VALUE_TYPE_F64 <= type && type <= VALUE_TYPE_I32
|
|
&& signature == num_sig_map[type - VALUE_TYPE_F64]) {
|
|
return true;
|
|
}
|
|
|
|
#if WASM_ENABLE_REF_TYPES != 0
|
|
if ('r' == signature && type == VALUE_TYPE_EXTERNREF)
|
|
return true;
|
|
#endif
|
|
|
|
/* TODO: a v128 parameter */
|
|
return false;
|
|
}
|
|
|
|
static bool
|
|
check_symbol_signature(const WASMType *type, const char *signature)
|
|
{
|
|
const char *p = signature, *p_end;
|
|
char sig;
|
|
uint32 i = 0;
|
|
|
|
if (!p || strlen(p) < 2)
|
|
return false;
|
|
|
|
p_end = p + strlen(signature);
|
|
|
|
if (*p++ != '(')
|
|
return false;
|
|
|
|
if ((uint32)(p_end - p) < (uint32)(type->param_count + 1))
|
|
/* signatures of parameters, and ')' */
|
|
return false;
|
|
|
|
for (i = 0; i < type->param_count; i++) {
|
|
sig = *p++;
|
|
|
|
/* a f64/f32/i64/i32/externref parameter */
|
|
if (compare_type_with_signautre(type->types[i], sig))
|
|
continue;
|
|
|
|
/* a pointer/string paramter */
|
|
if (type->types[i] != VALUE_TYPE_I32)
|
|
/* pointer and string must be i32 type */
|
|
return false;
|
|
|
|
if (sig == '*') {
|
|
/* it is a pointer */
|
|
if (i + 1 < type->param_count
|
|
&& type->types[i + 1] == VALUE_TYPE_I32 && *p == '~') {
|
|
/* pointer length followed */
|
|
i++;
|
|
p++;
|
|
}
|
|
}
|
|
else if (sig == '$') {
|
|
/* it is a string */
|
|
}
|
|
else {
|
|
/* invalid signature */
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if (*p++ != ')')
|
|
return false;
|
|
|
|
if (type->result_count) {
|
|
if (p >= p_end)
|
|
return false;
|
|
|
|
/* result types includes: f64,f32,i64,i32,externref */
|
|
if (!compare_type_with_signautre(type->types[i], *p))
|
|
return false;
|
|
|
|
p++;
|
|
}
|
|
|
|
if (*p != '\0')
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
static int
|
|
native_symbol_cmp(const void *native_symbol1, const void *native_symbol2)
|
|
{
|
|
return strcmp(((const NativeSymbol *)native_symbol1)->symbol,
|
|
((const NativeSymbol *)native_symbol2)->symbol);
|
|
}
|
|
|
|
static void *
|
|
lookup_symbol(NativeSymbol *native_symbols, uint32 n_native_symbols,
|
|
const char *symbol, const char **p_signature, void **p_attachment)
|
|
{
|
|
NativeSymbol *native_symbol, key = { 0 };
|
|
|
|
key.symbol = symbol;
|
|
|
|
if ((native_symbol = bsearch(&key, native_symbols, n_native_symbols,
|
|
sizeof(NativeSymbol), native_symbol_cmp))) {
|
|
*p_signature = native_symbol->signature;
|
|
*p_attachment = native_symbol->attachment;
|
|
return native_symbol->func_ptr;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/**
|
|
* allow func_type and all outputs, like p_signature, p_attachment and
|
|
* p_call_conv_raw to be NULL
|
|
*/
|
|
void *
|
|
wasm_native_resolve_symbol(const char *module_name, const char *field_name,
|
|
const WASMType *func_type, const char **p_signature,
|
|
void **p_attachment, bool *p_call_conv_raw)
|
|
{
|
|
NativeSymbolsNode *node, *node_next;
|
|
const char *signature = NULL;
|
|
void *func_ptr = NULL, *attachment;
|
|
|
|
node = g_native_symbols_list;
|
|
while (node) {
|
|
node_next = node->next;
|
|
if (!strcmp(node->module_name, module_name)) {
|
|
if ((func_ptr =
|
|
lookup_symbol(node->native_symbols, node->n_native_symbols,
|
|
field_name, &signature, &attachment))
|
|
|| (field_name[0] == '_'
|
|
&& (func_ptr = lookup_symbol(
|
|
node->native_symbols, node->n_native_symbols,
|
|
field_name + 1, &signature, &attachment))))
|
|
break;
|
|
}
|
|
node = node_next;
|
|
}
|
|
|
|
if (!p_signature || !p_attachment || !p_call_conv_raw)
|
|
return func_ptr;
|
|
|
|
if (func_ptr) {
|
|
if (signature && signature[0] != '\0') {
|
|
/* signature is not empty, check its format */
|
|
if (!func_type || !check_symbol_signature(func_type, signature)) {
|
|
#if WASM_ENABLE_WAMR_COMPILER == 0
|
|
/* Output warning except running aot compiler */
|
|
LOG_WARNING("failed to check signature '%s' and resolve "
|
|
"pointer params for import function (%s %s)\n",
|
|
signature, module_name, field_name);
|
|
#endif
|
|
return NULL;
|
|
}
|
|
else
|
|
/* Save signature for runtime to do pointer check and
|
|
address conversion */
|
|
*p_signature = signature;
|
|
}
|
|
else
|
|
/* signature is empty */
|
|
*p_signature = NULL;
|
|
|
|
*p_attachment = attachment;
|
|
*p_call_conv_raw = node->call_conv_raw;
|
|
}
|
|
|
|
return func_ptr;
|
|
}
|
|
|
|
static bool
|
|
register_natives(const char *module_name, NativeSymbol *native_symbols,
|
|
uint32 n_native_symbols, bool call_conv_raw)
|
|
{
|
|
NativeSymbolsNode *node;
|
|
|
|
if (!(node = wasm_runtime_malloc(sizeof(NativeSymbolsNode))))
|
|
return false;
|
|
#if WASM_ENABLE_MEMORY_TRACING != 0
|
|
os_printf("Register native, size: %u\n", sizeof(NativeSymbolsNode));
|
|
#endif
|
|
|
|
node->module_name = module_name;
|
|
node->native_symbols = native_symbols;
|
|
node->n_native_symbols = n_native_symbols;
|
|
node->call_conv_raw = call_conv_raw;
|
|
|
|
/* Add to list head */
|
|
node->next = g_native_symbols_list;
|
|
g_native_symbols_list = node;
|
|
|
|
qsort(native_symbols, n_native_symbols, sizeof(NativeSymbol),
|
|
native_symbol_cmp);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool
|
|
wasm_native_register_natives(const char *module_name,
|
|
NativeSymbol *native_symbols,
|
|
uint32 n_native_symbols)
|
|
{
|
|
return register_natives(module_name, native_symbols, n_native_symbols,
|
|
false);
|
|
}
|
|
|
|
bool
|
|
wasm_native_register_natives_raw(const char *module_name,
|
|
NativeSymbol *native_symbols,
|
|
uint32 n_native_symbols)
|
|
{
|
|
return register_natives(module_name, native_symbols, n_native_symbols,
|
|
true);
|
|
}
|
|
|
|
bool
|
|
wasm_native_unregister_natives(const char *module_name,
|
|
NativeSymbol *native_symbols)
|
|
{
|
|
NativeSymbolsNode **prevp;
|
|
NativeSymbolsNode *node;
|
|
|
|
prevp = &g_native_symbols_list;
|
|
while ((node = *prevp) != NULL) {
|
|
if (node->native_symbols == native_symbols
|
|
&& !strcmp(node->module_name, module_name)) {
|
|
*prevp = node->next;
|
|
wasm_runtime_free(node);
|
|
return true;
|
|
}
|
|
prevp = &node->next;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
#if WASM_ENABLE_MODULE_INST_CONTEXT != 0
|
|
static uint32
|
|
context_key_to_idx(void *key)
|
|
{
|
|
bh_assert(key != NULL);
|
|
uint32 idx = (uint32)(uintptr_t)key;
|
|
bh_assert(idx > 0);
|
|
bh_assert(idx <= WASM_MAX_INSTANCE_CONTEXTS);
|
|
return idx - 1;
|
|
}
|
|
|
|
static void *
|
|
context_idx_to_key(uint32 idx)
|
|
{
|
|
bh_assert(idx < WASM_MAX_INSTANCE_CONTEXTS);
|
|
return (void *)(uintptr_t)(idx + 1);
|
|
}
|
|
|
|
typedef void (*dtor_t)(WASMModuleInstanceCommon *, void *);
|
|
static dtor_t g_context_dtors[WASM_MAX_INSTANCE_CONTEXTS];
|
|
|
|
static void
|
|
dtor_noop(WASMModuleInstanceCommon *inst, void *ctx)
|
|
{}
|
|
|
|
void *
|
|
wasm_native_create_context_key(void (*dtor)(WASMModuleInstanceCommon *inst,
|
|
void *ctx))
|
|
{
|
|
uint32 i;
|
|
for (i = 0; i < WASM_MAX_INSTANCE_CONTEXTS; i++) {
|
|
if (g_context_dtors[i] == NULL) {
|
|
if (dtor == NULL) {
|
|
dtor = dtor_noop;
|
|
}
|
|
g_context_dtors[i] = dtor;
|
|
return context_idx_to_key(i);
|
|
}
|
|
}
|
|
LOG_ERROR("failed to allocate instance context key");
|
|
return NULL;
|
|
}
|
|
|
|
void
|
|
wasm_native_destroy_context_key(void *key)
|
|
{
|
|
uint32 idx = context_key_to_idx(key);
|
|
bh_assert(g_context_dtors[idx] != NULL);
|
|
g_context_dtors[idx] = NULL;
|
|
}
|
|
|
|
static WASMModuleInstanceExtraCommon *
|
|
wasm_module_inst_extra_common(WASMModuleInstanceCommon *inst)
|
|
{
|
|
#if WASM_ENABLE_INTERP != 0
|
|
if (inst->module_type == Wasm_Module_Bytecode) {
|
|
return &((WASMModuleInstance *)inst)->e->common;
|
|
}
|
|
#endif
|
|
#if WASM_ENABLE_AOT != 0
|
|
if (inst->module_type == Wasm_Module_AoT) {
|
|
return &((AOTModuleInstanceExtra *)((AOTModuleInstance *)inst)->e)
|
|
->common;
|
|
}
|
|
#endif
|
|
bh_assert(false);
|
|
return NULL;
|
|
}
|
|
|
|
void
|
|
wasm_native_set_context(WASMModuleInstanceCommon *inst, void *key, void *ctx)
|
|
{
|
|
uint32 idx = context_key_to_idx(key);
|
|
WASMModuleInstanceExtraCommon *common = wasm_module_inst_extra_common(inst);
|
|
common->contexts[idx] = ctx;
|
|
}
|
|
|
|
void
|
|
wasm_native_set_context_spread(WASMModuleInstanceCommon *inst, void *key,
|
|
void *ctx)
|
|
{
|
|
#if WASM_ENABLE_THREAD_MGR != 0
|
|
wasm_cluster_set_context(inst, key, ctx);
|
|
#else
|
|
wasm_native_set_context(inst, key, ctx);
|
|
#endif
|
|
}
|
|
|
|
void *
|
|
wasm_native_get_context(WASMModuleInstanceCommon *inst, void *key)
|
|
{
|
|
uint32 idx = context_key_to_idx(key);
|
|
WASMModuleInstanceExtraCommon *common = wasm_module_inst_extra_common(inst);
|
|
return common->contexts[idx];
|
|
}
|
|
|
|
void
|
|
wasm_native_call_context_dtors(WASMModuleInstanceCommon *inst)
|
|
{
|
|
WASMModuleInstanceExtraCommon *common = wasm_module_inst_extra_common(inst);
|
|
uint32 i;
|
|
for (i = 0; i < WASM_MAX_INSTANCE_CONTEXTS; i++) {
|
|
dtor_t dtor = g_context_dtors[i];
|
|
if (dtor != NULL) {
|
|
dtor(inst, common->contexts[i]);
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
wasm_native_inherit_contexts(WASMModuleInstanceCommon *child,
|
|
WASMModuleInstanceCommon *parent)
|
|
{
|
|
WASMModuleInstanceExtraCommon *parent_common =
|
|
wasm_module_inst_extra_common(parent);
|
|
WASMModuleInstanceExtraCommon *child_common =
|
|
wasm_module_inst_extra_common(child);
|
|
bh_memcpy_s(child_common->contexts,
|
|
sizeof(*child_common->contexts) * WASM_MAX_INSTANCE_CONTEXTS,
|
|
parent_common->contexts,
|
|
sizeof(*parent_common->contexts) * WASM_MAX_INSTANCE_CONTEXTS);
|
|
}
|
|
#endif /* WASM_ENABLE_MODULE_INST_CONTEXT != 0 */
|
|
|
|
#if WASM_ENABLE_LIBC_WASI != 0
|
|
WASIContext *
|
|
wasm_runtime_get_wasi_ctx(WASMModuleInstanceCommon *module_inst_comm)
|
|
{
|
|
return wasm_native_get_context(module_inst_comm, g_wasi_context_key);
|
|
}
|
|
|
|
void
|
|
wasm_runtime_set_wasi_ctx(WASMModuleInstanceCommon *module_inst_comm,
|
|
WASIContext *wasi_ctx)
|
|
{
|
|
wasm_native_set_context(module_inst_comm, g_wasi_context_key, wasi_ctx);
|
|
}
|
|
|
|
static void
|
|
wasi_context_dtor(WASMModuleInstanceCommon *inst, void *ctx)
|
|
{
|
|
if (ctx == NULL) {
|
|
return;
|
|
}
|
|
wasm_runtime_destroy_wasi(inst);
|
|
}
|
|
#endif /* end of WASM_ENABLE_LIBC_WASI */
|
|
|
|
#if WASM_ENABLE_QUICK_AOT_ENTRY != 0
|
|
static bool
|
|
quick_aot_entry_init();
|
|
#endif
|
|
|
|
bool
|
|
wasm_native_init()
|
|
{
|
|
#if WASM_ENABLE_SPEC_TEST != 0 || WASM_ENABLE_LIBC_BUILTIN != 0 \
|
|
|| WASM_ENABLE_BASE_LIB != 0 || WASM_ENABLE_LIBC_EMCC != 0 \
|
|
|| WASM_ENABLE_LIB_RATS != 0 || WASM_ENABLE_WASI_NN != 0 \
|
|
|| WASM_ENABLE_APP_FRAMEWORK != 0 || WASM_ENABLE_LIBC_WASI != 0 \
|
|
|| WASM_ENABLE_LIB_PTHREAD != 0 || WASM_ENABLE_LIB_WASI_THREADS != 0
|
|
NativeSymbol *native_symbols;
|
|
uint32 n_native_symbols;
|
|
#endif
|
|
|
|
#if WASM_ENABLE_LIBC_BUILTIN != 0
|
|
n_native_symbols = get_libc_builtin_export_apis(&native_symbols);
|
|
if (!wasm_native_register_natives("env", native_symbols, n_native_symbols))
|
|
goto fail;
|
|
#endif /* WASM_ENABLE_LIBC_BUILTIN */
|
|
|
|
#if WASM_ENABLE_SPEC_TEST
|
|
n_native_symbols = get_spectest_export_apis(&native_symbols);
|
|
if (!wasm_native_register_natives("spectest", native_symbols,
|
|
n_native_symbols))
|
|
goto fail;
|
|
#endif /* WASM_ENABLE_SPEC_TEST */
|
|
|
|
#if WASM_ENABLE_LIBC_WASI != 0
|
|
g_wasi_context_key = wasm_native_create_context_key(wasi_context_dtor);
|
|
if (g_wasi_context_key == NULL) {
|
|
goto fail;
|
|
}
|
|
n_native_symbols = get_libc_wasi_export_apis(&native_symbols);
|
|
if (!wasm_native_register_natives("wasi_unstable", native_symbols,
|
|
n_native_symbols))
|
|
goto fail;
|
|
if (!wasm_native_register_natives("wasi_snapshot_preview1", native_symbols,
|
|
n_native_symbols))
|
|
goto fail;
|
|
#endif
|
|
|
|
#if WASM_ENABLE_BASE_LIB != 0
|
|
n_native_symbols = get_base_lib_export_apis(&native_symbols);
|
|
if (n_native_symbols > 0
|
|
&& !wasm_native_register_natives("env", native_symbols,
|
|
n_native_symbols))
|
|
goto fail;
|
|
#endif
|
|
|
|
#if WASM_ENABLE_APP_FRAMEWORK != 0
|
|
n_native_symbols = get_ext_lib_export_apis(&native_symbols);
|
|
if (n_native_symbols > 0
|
|
&& !wasm_native_register_natives("env", native_symbols,
|
|
n_native_symbols))
|
|
goto fail;
|
|
#endif
|
|
|
|
#if WASM_ENABLE_LIB_PTHREAD != 0
|
|
if (!lib_pthread_init())
|
|
goto fail;
|
|
|
|
n_native_symbols = get_lib_pthread_export_apis(&native_symbols);
|
|
if (n_native_symbols > 0
|
|
&& !wasm_native_register_natives("env", native_symbols,
|
|
n_native_symbols))
|
|
goto fail;
|
|
#endif
|
|
|
|
#if WASM_ENABLE_LIB_WASI_THREADS != 0
|
|
if (!lib_wasi_threads_init())
|
|
goto fail;
|
|
|
|
n_native_symbols = get_lib_wasi_threads_export_apis(&native_symbols);
|
|
if (n_native_symbols > 0
|
|
&& !wasm_native_register_natives("wasi", native_symbols,
|
|
n_native_symbols))
|
|
goto fail;
|
|
#endif
|
|
|
|
#if WASM_ENABLE_LIBC_EMCC != 0
|
|
n_native_symbols = get_libc_emcc_export_apis(&native_symbols);
|
|
if (n_native_symbols > 0
|
|
&& !wasm_native_register_natives("env", native_symbols,
|
|
n_native_symbols))
|
|
goto fail;
|
|
#endif /* WASM_ENABLE_LIBC_EMCC */
|
|
|
|
#if WASM_ENABLE_LIB_RATS != 0
|
|
n_native_symbols = get_lib_rats_export_apis(&native_symbols);
|
|
if (n_native_symbols > 0
|
|
&& !wasm_native_register_natives("env", native_symbols,
|
|
n_native_symbols))
|
|
goto fail;
|
|
#endif /* WASM_ENABLE_LIB_RATS */
|
|
|
|
#if WASM_ENABLE_WASI_NN != 0
|
|
n_native_symbols = get_wasi_nn_export_apis(&native_symbols);
|
|
if (!wasm_native_register_natives("wasi_nn", native_symbols,
|
|
n_native_symbols))
|
|
goto fail;
|
|
#endif
|
|
|
|
#if WASM_ENABLE_QUICK_AOT_ENTRY != 0
|
|
if (!quick_aot_entry_init()) {
|
|
#if WASM_ENABLE_SPEC_TEST != 0 || WASM_ENABLE_LIBC_BUILTIN != 0 \
|
|
|| WASM_ENABLE_BASE_LIB != 0 || WASM_ENABLE_LIBC_EMCC != 0 \
|
|
|| WASM_ENABLE_LIB_RATS != 0 || WASM_ENABLE_WASI_NN != 0 \
|
|
|| WASM_ENABLE_APP_FRAMEWORK != 0 || WASM_ENABLE_LIBC_WASI != 0 \
|
|
|| WASM_ENABLE_LIB_PTHREAD != 0 || WASM_ENABLE_LIB_WASI_THREADS != 0
|
|
goto fail;
|
|
#else
|
|
return false;
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
return true;
|
|
#if WASM_ENABLE_SPEC_TEST != 0 || WASM_ENABLE_LIBC_BUILTIN != 0 \
|
|
|| WASM_ENABLE_BASE_LIB != 0 || WASM_ENABLE_LIBC_EMCC != 0 \
|
|
|| WASM_ENABLE_LIB_RATS != 0 || WASM_ENABLE_WASI_NN != 0 \
|
|
|| WASM_ENABLE_APP_FRAMEWORK != 0 || WASM_ENABLE_LIBC_WASI != 0 \
|
|
|| WASM_ENABLE_LIB_PTHREAD != 0 || WASM_ENABLE_LIB_WASI_THREADS != 0
|
|
fail:
|
|
wasm_native_destroy();
|
|
return false;
|
|
#endif
|
|
}
|
|
|
|
void
|
|
wasm_native_destroy()
|
|
{
|
|
NativeSymbolsNode *node, *node_next;
|
|
|
|
#if WASM_ENABLE_LIBC_WASI != 0
|
|
if (g_wasi_context_key != NULL) {
|
|
wasm_native_destroy_context_key(g_wasi_context_key);
|
|
g_wasi_context_key = NULL;
|
|
}
|
|
#endif
|
|
#if WASM_ENABLE_LIB_PTHREAD != 0
|
|
lib_pthread_destroy();
|
|
#endif
|
|
|
|
#if WASM_ENABLE_LIB_WASI_THREADS != 0
|
|
lib_wasi_threads_destroy();
|
|
#endif
|
|
|
|
node = g_native_symbols_list;
|
|
while (node) {
|
|
node_next = node->next;
|
|
wasm_runtime_free(node);
|
|
node = node_next;
|
|
}
|
|
|
|
g_native_symbols_list = NULL;
|
|
}
|
|
|
|
#if WASM_ENABLE_QUICK_AOT_ENTRY != 0
|
|
static void
|
|
invoke_no_args_v(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
void (*native_code)() = func_ptr;
|
|
native_code(exec_env);
|
|
}
|
|
static void
|
|
invoke_no_args_i(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
uint32 (*native_code)() = func_ptr;
|
|
argv_ret[0] = native_code(exec_env);
|
|
}
|
|
static void
|
|
invoke_no_args_I(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
uint64 (*native_code)() = func_ptr;
|
|
uint64 ret = native_code(exec_env);
|
|
PUT_I64_TO_ADDR(argv_ret, ret);
|
|
}
|
|
|
|
static void
|
|
invoke_i_v(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
void (*native_code)() = func_ptr;
|
|
native_code(exec_env, argv[0]);
|
|
}
|
|
static void
|
|
invoke_i_i(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
uint32 (*native_code)() = func_ptr;
|
|
argv_ret[0] = native_code(exec_env, argv[0]);
|
|
}
|
|
static void
|
|
invoke_i_I(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
uint64 (*native_code)() = func_ptr;
|
|
uint64 ret = native_code(exec_env, argv[0]);
|
|
PUT_I64_TO_ADDR(argv_ret, ret);
|
|
}
|
|
|
|
static void
|
|
invoke_I_v(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
void (*native_code)() = func_ptr;
|
|
native_code(exec_env, GET_I64_FROM_ADDR(argv));
|
|
}
|
|
static void
|
|
invoke_I_i(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
uint32 (*native_code)() = func_ptr;
|
|
argv_ret[0] = native_code(exec_env, GET_I64_FROM_ADDR(argv));
|
|
}
|
|
static void
|
|
invoke_I_I(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
uint64 (*native_code)() = func_ptr;
|
|
uint64 ret = native_code(exec_env, GET_I64_FROM_ADDR(argv));
|
|
PUT_I64_TO_ADDR(argv_ret, ret);
|
|
}
|
|
|
|
static void
|
|
invoke_ii_v(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
void (*native_code)() = func_ptr;
|
|
native_code(exec_env, argv[0], argv[1]);
|
|
}
|
|
static void
|
|
invoke_ii_i(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
uint32 (*native_code)() = func_ptr;
|
|
argv_ret[0] = native_code(exec_env, argv[0], argv[1]);
|
|
}
|
|
static void
|
|
invoke_ii_I(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
uint64 (*native_code)() = func_ptr;
|
|
uint64 ret = native_code(exec_env, argv[0], argv[1]);
|
|
PUT_I64_TO_ADDR(argv_ret, ret);
|
|
}
|
|
|
|
static void
|
|
invoke_iI_v(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
void (*native_code)() = func_ptr;
|
|
native_code(exec_env, argv[0], GET_I64_FROM_ADDR(argv + 1));
|
|
}
|
|
static void
|
|
invoke_iI_i(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
uint32 (*native_code)() = func_ptr;
|
|
argv_ret[0] = native_code(exec_env, argv[0], GET_I64_FROM_ADDR(argv + 1));
|
|
}
|
|
static void
|
|
invoke_iI_I(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
uint64 (*native_code)() = func_ptr;
|
|
uint64 ret = native_code(exec_env, argv[0], GET_I64_FROM_ADDR(argv + 1));
|
|
PUT_I64_TO_ADDR(argv_ret, ret);
|
|
}
|
|
|
|
static void
|
|
invoke_Ii_v(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
void (*native_code)() = func_ptr;
|
|
native_code(exec_env, GET_I64_FROM_ADDR(argv), argv[2]);
|
|
}
|
|
static void
|
|
invoke_Ii_i(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
uint32 (*native_code)() = func_ptr;
|
|
argv_ret[0] = native_code(exec_env, GET_I64_FROM_ADDR(argv), argv[2]);
|
|
}
|
|
static void
|
|
invoke_Ii_I(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
uint64 (*native_code)() = func_ptr;
|
|
uint64 ret = native_code(exec_env, GET_I64_FROM_ADDR(argv), argv[2]);
|
|
PUT_I64_TO_ADDR(argv_ret, ret);
|
|
}
|
|
|
|
static void
|
|
invoke_II_v(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
void (*native_code)() = func_ptr;
|
|
native_code(exec_env, GET_I64_FROM_ADDR(argv), GET_I64_FROM_ADDR(argv + 2));
|
|
}
|
|
static void
|
|
invoke_II_i(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
uint32 (*native_code)() = func_ptr;
|
|
argv_ret[0] = native_code(exec_env, GET_I64_FROM_ADDR(argv),
|
|
GET_I64_FROM_ADDR(argv + 2));
|
|
}
|
|
static void
|
|
invoke_II_I(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
uint64 (*native_code)() = func_ptr;
|
|
uint64 ret = native_code(exec_env, GET_I64_FROM_ADDR(argv),
|
|
GET_I64_FROM_ADDR(argv + 2));
|
|
PUT_I64_TO_ADDR(argv_ret, ret);
|
|
}
|
|
|
|
static void
|
|
invoke_iii_v(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
void (*native_code)() = func_ptr;
|
|
native_code(exec_env, argv[0], argv[1], argv[2]);
|
|
}
|
|
static void
|
|
invoke_iii_i(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
uint32 (*native_code)() = func_ptr;
|
|
argv_ret[0] = native_code(exec_env, argv[0], argv[1], argv[2]);
|
|
}
|
|
static void
|
|
invoke_iii_I(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
uint64 (*native_code)() = func_ptr;
|
|
uint64 ret = native_code(exec_env, argv[0], argv[1], argv[2]);
|
|
PUT_I64_TO_ADDR(argv_ret, ret);
|
|
}
|
|
|
|
static void
|
|
invoke_iiI_v(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
void (*native_code)() = func_ptr;
|
|
native_code(exec_env, argv[0], argv[1], GET_I64_FROM_ADDR(argv + 2));
|
|
}
|
|
static void
|
|
invoke_iiI_i(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
uint32 (*native_code)() = func_ptr;
|
|
argv_ret[0] =
|
|
native_code(exec_env, argv[0], argv[1], GET_I64_FROM_ADDR(argv + 2));
|
|
}
|
|
static void
|
|
invoke_iiI_I(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
uint64 (*native_code)() = func_ptr;
|
|
uint64 ret =
|
|
native_code(exec_env, argv[0], argv[1], GET_I64_FROM_ADDR(argv + 2));
|
|
PUT_I64_TO_ADDR(argv_ret, ret);
|
|
}
|
|
|
|
static void
|
|
invoke_iIi_v(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
void (*native_code)() = func_ptr;
|
|
native_code(exec_env, argv[0], GET_I64_FROM_ADDR(argv + 1), argv[3]);
|
|
}
|
|
static void
|
|
invoke_iIi_i(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
uint32 (*native_code)() = func_ptr;
|
|
argv_ret[0] =
|
|
native_code(exec_env, argv[0], GET_I64_FROM_ADDR(argv + 1), argv[3]);
|
|
}
|
|
static void
|
|
invoke_iIi_I(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
uint64 (*native_code)() = func_ptr;
|
|
uint64 ret =
|
|
native_code(exec_env, argv[0], GET_I64_FROM_ADDR(argv + 1), argv[3]);
|
|
PUT_I64_TO_ADDR(argv_ret, ret);
|
|
}
|
|
|
|
static void
|
|
invoke_iII_v(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
void (*native_code)() = func_ptr;
|
|
native_code(exec_env, argv[0], GET_I64_FROM_ADDR(argv + 1),
|
|
GET_I64_FROM_ADDR(argv + 3));
|
|
}
|
|
static void
|
|
invoke_iII_i(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
uint32 (*native_code)() = func_ptr;
|
|
argv_ret[0] = native_code(exec_env, argv[0], GET_I64_FROM_ADDR(argv + 1),
|
|
GET_I64_FROM_ADDR(argv + 3));
|
|
}
|
|
static void
|
|
invoke_iII_I(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
uint64 (*native_code)() = func_ptr;
|
|
uint64 ret = native_code(exec_env, argv[0], GET_I64_FROM_ADDR(argv + 1),
|
|
GET_I64_FROM_ADDR(argv + 3));
|
|
PUT_I64_TO_ADDR(argv_ret, ret);
|
|
}
|
|
|
|
static void
|
|
invoke_Iii_v(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
void (*native_code)() = func_ptr;
|
|
native_code(exec_env, GET_I64_FROM_ADDR(argv), argv[2], argv[3]);
|
|
}
|
|
static void
|
|
invoke_Iii_i(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
uint32 (*native_code)() = func_ptr;
|
|
argv_ret[0] =
|
|
native_code(exec_env, GET_I64_FROM_ADDR(argv), argv[2], argv[3]);
|
|
}
|
|
static void
|
|
invoke_Iii_I(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
uint64 (*native_code)() = func_ptr;
|
|
uint64 ret =
|
|
native_code(exec_env, GET_I64_FROM_ADDR(argv), argv[2], argv[3]);
|
|
PUT_I64_TO_ADDR(argv_ret, ret);
|
|
}
|
|
|
|
static void
|
|
invoke_IiI_v(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
void (*native_code)() = func_ptr;
|
|
native_code(exec_env, GET_I64_FROM_ADDR(argv), argv[2],
|
|
GET_I64_FROM_ADDR(argv + 3));
|
|
}
|
|
static void
|
|
invoke_IiI_i(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
uint32 (*native_code)() = func_ptr;
|
|
argv_ret[0] = native_code(exec_env, GET_I64_FROM_ADDR(argv), argv[2],
|
|
GET_I64_FROM_ADDR(argv + 3));
|
|
}
|
|
static void
|
|
invoke_IiI_I(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
uint64 (*native_code)() = func_ptr;
|
|
uint64 ret = native_code(exec_env, GET_I64_FROM_ADDR(argv), argv[2],
|
|
GET_I64_FROM_ADDR(argv + 3));
|
|
PUT_I64_TO_ADDR(argv_ret, ret);
|
|
}
|
|
|
|
static void
|
|
invoke_IIi_v(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
void (*native_code)() = func_ptr;
|
|
native_code(exec_env, GET_I64_FROM_ADDR(argv), GET_I64_FROM_ADDR(argv + 2),
|
|
argv[4]);
|
|
}
|
|
static void
|
|
invoke_IIi_i(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
uint32 (*native_code)() = func_ptr;
|
|
argv_ret[0] = native_code(exec_env, GET_I64_FROM_ADDR(argv),
|
|
GET_I64_FROM_ADDR(argv + 2), argv[4]);
|
|
}
|
|
static void
|
|
invoke_IIi_I(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
uint64 (*native_code)() = func_ptr;
|
|
uint64 ret = native_code(exec_env, GET_I64_FROM_ADDR(argv),
|
|
GET_I64_FROM_ADDR(argv + 2), argv[4]);
|
|
PUT_I64_TO_ADDR(argv_ret, ret);
|
|
}
|
|
|
|
static void
|
|
invoke_III_v(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
void (*native_code)() = func_ptr;
|
|
native_code(exec_env, GET_I64_FROM_ADDR(argv), GET_I64_FROM_ADDR(argv + 2),
|
|
GET_I64_FROM_ADDR(argv + 4));
|
|
}
|
|
static void
|
|
invoke_III_i(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
uint32 (*native_code)() = func_ptr;
|
|
argv_ret[0] =
|
|
native_code(exec_env, GET_I64_FROM_ADDR(argv),
|
|
GET_I64_FROM_ADDR(argv + 2), GET_I64_FROM_ADDR(argv + 4));
|
|
}
|
|
static void
|
|
invoke_III_I(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
uint64 (*native_code)() = func_ptr;
|
|
uint64 ret =
|
|
native_code(exec_env, GET_I64_FROM_ADDR(argv),
|
|
GET_I64_FROM_ADDR(argv + 2), GET_I64_FROM_ADDR(argv + 4));
|
|
PUT_I64_TO_ADDR(argv_ret, ret);
|
|
}
|
|
|
|
static void
|
|
invoke_iiii_v(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
void (*native_code)() = func_ptr;
|
|
native_code(exec_env, argv[0], argv[1], argv[2], argv[3]);
|
|
}
|
|
static void
|
|
invoke_iiii_i(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
uint32 (*native_code)() = func_ptr;
|
|
argv_ret[0] = native_code(exec_env, argv[0], argv[1], argv[2], argv[3]);
|
|
}
|
|
static void
|
|
invoke_iiii_I(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
uint64 (*native_code)() = func_ptr;
|
|
uint64 ret = native_code(exec_env, argv[0], argv[1], argv[2], argv[3]);
|
|
PUT_I64_TO_ADDR(argv_ret, ret);
|
|
}
|
|
|
|
static void
|
|
invoke_iiiI_v(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
void (*native_code)() = func_ptr;
|
|
native_code(exec_env, argv[0], argv[1], argv[2],
|
|
GET_I64_FROM_ADDR(argv + 3));
|
|
}
|
|
static void
|
|
invoke_iiiI_i(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
uint32 (*native_code)() = func_ptr;
|
|
argv_ret[0] = native_code(exec_env, argv[0], argv[1], argv[2],
|
|
GET_I64_FROM_ADDR(argv + 3));
|
|
}
|
|
static void
|
|
invoke_iiiI_I(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
uint64 (*native_code)() = func_ptr;
|
|
uint64 ret = native_code(exec_env, argv[0], argv[1], argv[2],
|
|
GET_I64_FROM_ADDR(argv + 3));
|
|
PUT_I64_TO_ADDR(argv_ret, ret);
|
|
}
|
|
|
|
static void
|
|
invoke_iiIi_v(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
void (*native_code)() = func_ptr;
|
|
native_code(exec_env, argv[0], argv[1], GET_I64_FROM_ADDR(argv + 2),
|
|
argv[4]);
|
|
}
|
|
static void
|
|
invoke_iiIi_i(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
uint32 (*native_code)() = func_ptr;
|
|
argv_ret[0] = native_code(exec_env, argv[0], argv[1],
|
|
GET_I64_FROM_ADDR(argv + 2), argv[4]);
|
|
}
|
|
static void
|
|
invoke_iiIi_I(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
uint64 (*native_code)() = func_ptr;
|
|
uint64 ret = native_code(exec_env, argv[0], argv[1],
|
|
GET_I64_FROM_ADDR(argv + 2), argv[4]);
|
|
PUT_I64_TO_ADDR(argv_ret, ret);
|
|
}
|
|
|
|
static void
|
|
invoke_iiII_v(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
void (*native_code)() = func_ptr;
|
|
native_code(exec_env, argv[0], argv[1], GET_I64_FROM_ADDR(argv + 2),
|
|
GET_I64_FROM_ADDR(argv + 4));
|
|
}
|
|
static void
|
|
invoke_iiII_i(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
uint32 (*native_code)() = func_ptr;
|
|
argv_ret[0] =
|
|
native_code(exec_env, argv[0], argv[1], GET_I64_FROM_ADDR(argv + 2),
|
|
GET_I64_FROM_ADDR(argv + 4));
|
|
}
|
|
static void
|
|
invoke_iiII_I(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
uint64 (*native_code)() = func_ptr;
|
|
uint64 ret =
|
|
native_code(exec_env, argv[0], argv[1], GET_I64_FROM_ADDR(argv + 2),
|
|
GET_I64_FROM_ADDR(argv + 4));
|
|
PUT_I64_TO_ADDR(argv_ret, ret);
|
|
}
|
|
|
|
static void
|
|
invoke_iIii_v(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
void (*native_code)() = func_ptr;
|
|
native_code(exec_env, argv[0], GET_I64_FROM_ADDR(argv + 1), argv[3],
|
|
argv[4]);
|
|
}
|
|
static void
|
|
invoke_iIii_i(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
uint32 (*native_code)() = func_ptr;
|
|
argv_ret[0] = native_code(exec_env, argv[0], GET_I64_FROM_ADDR(argv + 1),
|
|
argv[3], argv[4]);
|
|
}
|
|
static void
|
|
invoke_iIii_I(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
uint64 (*native_code)() = func_ptr;
|
|
uint64 ret = native_code(exec_env, argv[0], GET_I64_FROM_ADDR(argv + 1),
|
|
argv[3], argv[4]);
|
|
PUT_I64_TO_ADDR(argv_ret, ret);
|
|
}
|
|
|
|
static void
|
|
invoke_iIiI_v(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
void (*native_code)() = func_ptr;
|
|
native_code(exec_env, argv[0], GET_I64_FROM_ADDR(argv + 1), argv[3],
|
|
GET_I64_FROM_ADDR(argv + 4));
|
|
}
|
|
static void
|
|
invoke_iIiI_i(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
uint32 (*native_code)() = func_ptr;
|
|
argv_ret[0] = native_code(exec_env, argv[0], GET_I64_FROM_ADDR(argv + 1),
|
|
argv[3], GET_I64_FROM_ADDR(argv + 4));
|
|
}
|
|
static void
|
|
invoke_iIiI_I(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
uint64 (*native_code)() = func_ptr;
|
|
uint64 ret = native_code(exec_env, argv[0], GET_I64_FROM_ADDR(argv + 1),
|
|
argv[3], GET_I64_FROM_ADDR(argv + 4));
|
|
PUT_I64_TO_ADDR(argv_ret, ret);
|
|
}
|
|
|
|
static void
|
|
invoke_iIIi_v(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
void (*native_code)() = func_ptr;
|
|
native_code(exec_env, argv[0], GET_I64_FROM_ADDR(argv + 1),
|
|
GET_I64_FROM_ADDR(argv + 3), argv[5]);
|
|
}
|
|
static void
|
|
invoke_iIIi_i(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
uint32 (*native_code)() = func_ptr;
|
|
argv_ret[0] = native_code(exec_env, argv[0], GET_I64_FROM_ADDR(argv + 1),
|
|
GET_I64_FROM_ADDR(argv + 3), argv[5]);
|
|
}
|
|
static void
|
|
invoke_iIIi_I(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
uint64 (*native_code)() = func_ptr;
|
|
uint64 ret = native_code(exec_env, argv[0], GET_I64_FROM_ADDR(argv + 1),
|
|
GET_I64_FROM_ADDR(argv + 3), argv[5]);
|
|
PUT_I64_TO_ADDR(argv_ret, ret);
|
|
}
|
|
|
|
static void
|
|
invoke_iIII_v(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
void (*native_code)() = func_ptr;
|
|
native_code(exec_env, argv[0], GET_I64_FROM_ADDR(argv + 1),
|
|
GET_I64_FROM_ADDR(argv + 3), GET_I64_FROM_ADDR(argv + 5));
|
|
}
|
|
static void
|
|
invoke_iIII_i(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
uint32 (*native_code)() = func_ptr;
|
|
argv_ret[0] =
|
|
native_code(exec_env, argv[0], GET_I64_FROM_ADDR(argv + 1),
|
|
GET_I64_FROM_ADDR(argv + 3), GET_I64_FROM_ADDR(argv + 5));
|
|
}
|
|
static void
|
|
invoke_iIII_I(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
uint64 (*native_code)() = func_ptr;
|
|
uint64 ret =
|
|
native_code(exec_env, argv[0], GET_I64_FROM_ADDR(argv + 1),
|
|
GET_I64_FROM_ADDR(argv + 3), GET_I64_FROM_ADDR(argv + 5));
|
|
PUT_I64_TO_ADDR(argv_ret, ret);
|
|
}
|
|
|
|
static void
|
|
invoke_Iiii_v(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
void (*native_code)() = func_ptr;
|
|
native_code(exec_env, GET_I64_FROM_ADDR(argv), argv[2], argv[3], argv[4]);
|
|
}
|
|
static void
|
|
invoke_Iiii_i(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
uint32 (*native_code)() = func_ptr;
|
|
argv_ret[0] = native_code(exec_env, GET_I64_FROM_ADDR(argv), argv[2],
|
|
argv[3], argv[4]);
|
|
}
|
|
static void
|
|
invoke_Iiii_I(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
uint64 (*native_code)() = func_ptr;
|
|
uint64 ret = native_code(exec_env, GET_I64_FROM_ADDR(argv), argv[2],
|
|
argv[3], argv[4]);
|
|
PUT_I64_TO_ADDR(argv_ret, ret);
|
|
}
|
|
|
|
static void
|
|
invoke_IiiI_v(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
void (*native_code)() = func_ptr;
|
|
native_code(exec_env, GET_I64_FROM_ADDR(argv), argv[2], argv[3],
|
|
GET_I64_FROM_ADDR(argv + 4));
|
|
}
|
|
|
|
static void
|
|
invoke_IiiI_i(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
uint32 (*native_code)() = func_ptr;
|
|
argv_ret[0] = native_code(exec_env, GET_I64_FROM_ADDR(argv), argv[2],
|
|
argv[3], GET_I64_FROM_ADDR(argv + 4));
|
|
}
|
|
|
|
static void
|
|
invoke_IiiI_I(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
uint64 (*native_code)() = func_ptr;
|
|
uint64 ret = native_code(exec_env, GET_I64_FROM_ADDR(argv), argv[2],
|
|
argv[3], GET_I64_FROM_ADDR(argv + 4));
|
|
PUT_I64_TO_ADDR(argv_ret, ret);
|
|
}
|
|
|
|
static void
|
|
invoke_IiIi_v(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
void (*native_code)() = func_ptr;
|
|
native_code(exec_env, GET_I64_FROM_ADDR(argv), argv[2],
|
|
GET_I64_FROM_ADDR(argv + 3), argv[5]);
|
|
}
|
|
static void
|
|
invoke_IiIi_i(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
uint32 (*native_code)() = func_ptr;
|
|
argv_ret[0] = native_code(exec_env, GET_I64_FROM_ADDR(argv), argv[2],
|
|
GET_I64_FROM_ADDR(argv + 3), argv[5]);
|
|
}
|
|
static void
|
|
invoke_IiIi_I(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
uint64 (*native_code)() = func_ptr;
|
|
uint64 ret = native_code(exec_env, GET_I64_FROM_ADDR(argv), argv[2],
|
|
GET_I64_FROM_ADDR(argv + 3), argv[5]);
|
|
PUT_I64_TO_ADDR(argv_ret, ret);
|
|
}
|
|
|
|
static void
|
|
invoke_IiII_v(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
void (*native_code)() = func_ptr;
|
|
native_code(exec_env, GET_I64_FROM_ADDR(argv), argv[2],
|
|
GET_I64_FROM_ADDR(argv + 3), GET_I64_FROM_ADDR(argv + 5));
|
|
}
|
|
static void
|
|
invoke_IiII_i(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
uint32 (*native_code)() = func_ptr;
|
|
argv_ret[0] =
|
|
native_code(exec_env, GET_I64_FROM_ADDR(argv), argv[2],
|
|
GET_I64_FROM_ADDR(argv + 3), GET_I64_FROM_ADDR(argv + 5));
|
|
}
|
|
static void
|
|
invoke_IiII_I(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
uint64 (*native_code)() = func_ptr;
|
|
uint64 ret =
|
|
native_code(exec_env, GET_I64_FROM_ADDR(argv), argv[2],
|
|
GET_I64_FROM_ADDR(argv + 3), GET_I64_FROM_ADDR(argv + 5));
|
|
PUT_I64_TO_ADDR(argv_ret, ret);
|
|
}
|
|
|
|
static void
|
|
invoke_IIii_v(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
void (*native_code)() = func_ptr;
|
|
native_code(exec_env, GET_I64_FROM_ADDR(argv), GET_I64_FROM_ADDR(argv + 2),
|
|
argv[4], argv[5]);
|
|
}
|
|
static void
|
|
invoke_IIii_i(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
uint32 (*native_code)() = func_ptr;
|
|
argv_ret[0] = native_code(exec_env, GET_I64_FROM_ADDR(argv),
|
|
GET_I64_FROM_ADDR(argv + 2), argv[4], argv[5]);
|
|
}
|
|
static void
|
|
invoke_IIii_I(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
uint64 (*native_code)() = func_ptr;
|
|
uint64 ret = native_code(exec_env, GET_I64_FROM_ADDR(argv),
|
|
GET_I64_FROM_ADDR(argv + 2), argv[4], argv[5]);
|
|
PUT_I64_TO_ADDR(argv_ret, ret);
|
|
}
|
|
|
|
static void
|
|
invoke_IIiI_v(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
void (*native_code)() = func_ptr;
|
|
native_code(exec_env, GET_I64_FROM_ADDR(argv), GET_I64_FROM_ADDR(argv + 2),
|
|
argv[4], GET_I64_FROM_ADDR(argv + 5));
|
|
}
|
|
static void
|
|
invoke_IIiI_i(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
uint32 (*native_code)() = func_ptr;
|
|
argv_ret[0] = native_code(exec_env, GET_I64_FROM_ADDR(argv),
|
|
GET_I64_FROM_ADDR(argv + 2), argv[4],
|
|
GET_I64_FROM_ADDR(argv + 5));
|
|
}
|
|
static void
|
|
invoke_IIiI_I(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
uint64 (*native_code)() = func_ptr;
|
|
uint64 ret = native_code(exec_env, GET_I64_FROM_ADDR(argv),
|
|
GET_I64_FROM_ADDR(argv + 2), argv[4],
|
|
GET_I64_FROM_ADDR(argv + 5));
|
|
PUT_I64_TO_ADDR(argv_ret, ret);
|
|
}
|
|
|
|
static void
|
|
invoke_IIIi_v(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
void (*native_code)() = func_ptr;
|
|
native_code(exec_env, GET_I64_FROM_ADDR(argv), GET_I64_FROM_ADDR(argv + 2),
|
|
GET_I64_FROM_ADDR(argv + 4), argv[6]);
|
|
}
|
|
static void
|
|
invoke_IIIi_i(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
uint32 (*native_code)() = func_ptr;
|
|
argv_ret[0] = native_code(exec_env, GET_I64_FROM_ADDR(argv),
|
|
GET_I64_FROM_ADDR(argv + 2),
|
|
GET_I64_FROM_ADDR(argv + 4), argv[6]);
|
|
}
|
|
static void
|
|
invoke_IIIi_I(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
uint64 (*native_code)() = func_ptr;
|
|
uint64 ret = native_code(exec_env, GET_I64_FROM_ADDR(argv),
|
|
GET_I64_FROM_ADDR(argv + 2),
|
|
GET_I64_FROM_ADDR(argv + 4), argv[6]);
|
|
PUT_I64_TO_ADDR(argv_ret, ret);
|
|
}
|
|
|
|
static void
|
|
invoke_IIII_v(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
void (*native_code)() = func_ptr;
|
|
native_code(exec_env, GET_I64_FROM_ADDR(argv), GET_I64_FROM_ADDR(argv + 2),
|
|
GET_I64_FROM_ADDR(argv + 4), GET_I64_FROM_ADDR(argv + 6));
|
|
}
|
|
static void
|
|
invoke_IIII_i(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
uint32 (*native_code)() = func_ptr;
|
|
argv_ret[0] = native_code(
|
|
exec_env, GET_I64_FROM_ADDR(argv), GET_I64_FROM_ADDR(argv + 2),
|
|
GET_I64_FROM_ADDR(argv + 4), GET_I64_FROM_ADDR(argv + 6));
|
|
}
|
|
static void
|
|
invoke_IIII_I(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
uint64 (*native_code)() = func_ptr;
|
|
uint64 ret = native_code(
|
|
exec_env, GET_I64_FROM_ADDR(argv), GET_I64_FROM_ADDR(argv + 2),
|
|
GET_I64_FROM_ADDR(argv + 4), GET_I64_FROM_ADDR(argv + 6));
|
|
PUT_I64_TO_ADDR(argv_ret, ret);
|
|
}
|
|
|
|
static void
|
|
invoke_iiiii_v(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
void (*native_code)() = func_ptr;
|
|
native_code(exec_env, argv[0], argv[1], argv[2], argv[3], argv[4]);
|
|
}
|
|
static void
|
|
invoke_iiiii_i(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
uint32 (*native_code)() = func_ptr;
|
|
argv_ret[0] =
|
|
native_code(exec_env, argv[0], argv[1], argv[2], argv[3], argv[4]);
|
|
}
|
|
static void
|
|
invoke_iiiii_I(void *func_ptr, uint8 ret_type, void *exec_env, uint32 *argv,
|
|
uint32 *argv_ret)
|
|
{
|
|
uint64 (*native_code)() = func_ptr;
|
|
uint64 ret =
|
|
native_code(exec_env, argv[0], argv[1], argv[2], argv[3], argv[4]);
|
|
PUT_I64_TO_ADDR(argv_ret, ret);
|
|
}
|
|
|
|
typedef struct QuickAOTEntry {
|
|
const char *signature;
|
|
void *func_ptr;
|
|
} QuickAOTEntry;
|
|
|
|
/* clang-format off */
|
|
static QuickAOTEntry quick_aot_entries[] = {
|
|
{ "()v", invoke_no_args_v },
|
|
{ "()i", invoke_no_args_i },
|
|
{ "()I", invoke_no_args_I },
|
|
|
|
{ "(i)v", invoke_i_v }, { "(i)i", invoke_i_i }, { "(i)I", invoke_i_I },
|
|
{ "(I)v", invoke_I_v }, { "(I)i", invoke_I_i }, { "(I)I", invoke_I_I },
|
|
|
|
{ "(ii)v", invoke_ii_v }, { "(ii)i", invoke_ii_i }, { "(ii)I", invoke_ii_I },
|
|
{ "(iI)v", invoke_iI_v }, { "(iI)i", invoke_iI_i }, { "(iI)I", invoke_iI_I },
|
|
{ "(Ii)v", invoke_Ii_v }, { "(Ii)i", invoke_Ii_i }, { "(Ii)I", invoke_Ii_I },
|
|
{ "(II)v", invoke_II_v }, { "(II)i", invoke_II_i }, { "(II)I", invoke_II_I },
|
|
|
|
{ "(iii)v", invoke_iii_v }, { "(iii)i", invoke_iii_i }, { "(iii)I", invoke_iii_I },
|
|
{ "(iiI)v", invoke_iiI_v }, { "(iiI)i", invoke_iiI_i }, { "(iiI)I", invoke_iiI_I },
|
|
{ "(iIi)v", invoke_iIi_v }, { "(iIi)i", invoke_iIi_i }, { "(iIi)I", invoke_iIi_I },
|
|
{ "(iII)v", invoke_iII_v }, { "(iII)i", invoke_iII_i }, { "(iII)I", invoke_iII_I },
|
|
{ "(Iii)v", invoke_Iii_v }, { "(Iii)i", invoke_Iii_i }, { "(Iii)I", invoke_Iii_I },
|
|
{ "(IiI)v", invoke_IiI_v }, { "(IiI)i", invoke_IiI_i }, { "(IiI)I", invoke_IiI_I },
|
|
{ "(IIi)v", invoke_IIi_v }, { "(IIi)i", invoke_IIi_i }, { "(IIi)I", invoke_IIi_I },
|
|
{ "(III)v", invoke_III_v }, { "(III)i", invoke_III_i }, { "(III)I", invoke_III_I },
|
|
|
|
{ "(iiii)v", invoke_iiii_v }, { "(iiii)i", invoke_iiii_i }, { "(iiii)I", invoke_iiii_I },
|
|
{ "(iiiI)v", invoke_iiiI_v }, { "(iiiI)i", invoke_iiiI_i }, { "(iiiI)I", invoke_iiiI_I },
|
|
{ "(iiIi)v", invoke_iiIi_v }, { "(iiIi)i", invoke_iiIi_i }, { "(iiIi)I", invoke_iiIi_I },
|
|
{ "(iiII)v", invoke_iiII_v }, { "(iiII)i", invoke_iiII_i }, { "(iiII)I", invoke_iiII_I },
|
|
{ "(iIii)v", invoke_iIii_v }, { "(iIii)i", invoke_iIii_i }, { "(iIii)I", invoke_iIii_I },
|
|
{ "(iIiI)v", invoke_iIiI_v }, { "(iIiI)i", invoke_iIiI_i }, { "(iIiI)I", invoke_iIiI_I },
|
|
{ "(iIIi)v", invoke_iIIi_v }, { "(iIIi)i", invoke_iIIi_i }, { "(iIIi)I", invoke_iIIi_I },
|
|
{ "(iIII)v", invoke_iIII_v }, { "(iIII)i", invoke_iIII_i }, { "(iIII)I", invoke_iIII_I },
|
|
{ "(Iiii)v", invoke_Iiii_v }, { "(Iiii)i", invoke_Iiii_i }, { "(Iiii)I", invoke_Iiii_I },
|
|
{ "(IiiI)v", invoke_IiiI_v }, { "(IiiI)i", invoke_IiiI_i }, { "(IiiI)I", invoke_IiiI_I },
|
|
{ "(IiIi)v", invoke_IiIi_v }, { "(IiIi)i", invoke_IiIi_i }, { "(IiIi)I", invoke_IiIi_I },
|
|
{ "(IiII)v", invoke_IiII_v }, { "(IiII)i", invoke_IiII_i }, { "(IiII)I", invoke_IiII_I },
|
|
{ "(IIii)v", invoke_IIii_v }, { "(IIii)i", invoke_IIii_i }, { "(IIii)I", invoke_IIii_I },
|
|
{ "(IIiI)v", invoke_IIiI_v }, { "(IIiI)i", invoke_IIiI_i }, { "(IIiI)I", invoke_IIiI_I },
|
|
{ "(IIIi)v", invoke_IIIi_v }, { "(IIIi)i", invoke_IIIi_i }, { "(IIIi)I", invoke_IIIi_I },
|
|
{ "(IIII)v", invoke_IIII_v }, { "(IIII)i", invoke_IIII_i }, { "(IIII)I", invoke_IIII_I },
|
|
|
|
{ "(iiiii)v", invoke_iiiii_v }, { "(iiiii)i", invoke_iiiii_i }, { "(iiiii)I", invoke_iiiii_I },
|
|
};
|
|
/* clang-format on */
|
|
|
|
static int
|
|
quick_aot_entry_cmp(const void *quick_aot_entry1, const void *quick_aot_entry2)
|
|
{
|
|
return strcmp(((const QuickAOTEntry *)quick_aot_entry1)->signature,
|
|
((const QuickAOTEntry *)quick_aot_entry2)->signature);
|
|
}
|
|
|
|
static bool
|
|
quick_aot_entry_init()
|
|
{
|
|
qsort(quick_aot_entries, sizeof(quick_aot_entries) / sizeof(QuickAOTEntry),
|
|
sizeof(QuickAOTEntry), quick_aot_entry_cmp);
|
|
|
|
return true;
|
|
}
|
|
|
|
void *
|
|
wasm_native_lookup_quick_aot_entry(const WASMType *func_type)
|
|
{
|
|
char signature[16] = { 0 };
|
|
uint32 param_count = func_type->param_count;
|
|
uint32 result_count = func_type->result_count, i, j = 0;
|
|
const uint8 *types = func_type->types;
|
|
QuickAOTEntry *quick_aot_entry, key = { 0 };
|
|
|
|
if (param_count > 5 || result_count > 1)
|
|
return NULL;
|
|
|
|
signature[j++] = '(';
|
|
|
|
for (i = 0; i < param_count; i++) {
|
|
if (types[i] == VALUE_TYPE_I32)
|
|
signature[j++] = 'i';
|
|
else if (types[i] == VALUE_TYPE_I64)
|
|
signature[j++] = 'I';
|
|
else
|
|
return NULL;
|
|
}
|
|
|
|
signature[j++] = ')';
|
|
|
|
if (result_count == 0) {
|
|
signature[j++] = 'v';
|
|
}
|
|
else {
|
|
if (types[i] == VALUE_TYPE_I32)
|
|
signature[j++] = 'i';
|
|
else if (types[i] == VALUE_TYPE_I64)
|
|
signature[j++] = 'I';
|
|
else
|
|
return NULL;
|
|
}
|
|
|
|
key.signature = signature;
|
|
if ((quick_aot_entry =
|
|
bsearch(&key, quick_aot_entries,
|
|
sizeof(quick_aot_entries) / sizeof(QuickAOTEntry),
|
|
sizeof(QuickAOTEntry), quick_aot_entry_cmp))) {
|
|
return quick_aot_entry->func_ptr;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
#endif /* end of WASM_ENABLE_QUICK_AOT_ENTRY != 0 */
|