mirror of
https://github.com/bytecodealliance/wasm-micro-runtime.git
synced 2024-11-26 15:32:05 +00:00
Allow not copying the wasm binary in wasm-c-api and not referring to the binary in wasm/aot loader (#3389)
Add flag `LoadArgs.clone_wasm_binary` to control whether to clone the wasm/aot binary in wasm-c-api module. If false, API `wasm_module_new_ex` won't clone the binary, which may reduce the footprint. Add flag `LoadArgs.wasm_binary_freeable` to control whether the wasm/aot binary may be freed after instantiation for wamr API `wasm_runtime_load_ex`, if yes, then for some running modes, the wasm/aot module doesn't refer to the input binary again so developer can free it after instantiation to reduce the footprint. And add API `wasm_module_is_underlying_binary_freeable` and `wasm_runtime_is_underlying_binary_freeable` to check whether the input binary can be freed after instantiation for wasm-c-api and wamr api. And add sample to illustrate it.
This commit is contained in:
parent
51ecfd6673
commit
6b1d81650d
|
@ -3852,6 +3852,7 @@ create_module(char *name, char *error_buf, uint32 error_buf_size)
|
|||
module->module_type = Wasm_Module_AoT;
|
||||
|
||||
module->name = name;
|
||||
module->is_binary_freeable = false;
|
||||
|
||||
#if WASM_ENABLE_MULTI_MODULE != 0
|
||||
module->import_module_list = &module->import_module_list_head;
|
||||
|
@ -4082,8 +4083,8 @@ fail:
|
|||
}
|
||||
|
||||
static bool
|
||||
load(const uint8 *buf, uint32 size, AOTModule *module, char *error_buf,
|
||||
uint32 error_buf_size)
|
||||
load(const uint8 *buf, uint32 size, AOTModule *module,
|
||||
bool wasm_binary_freeable, char *error_buf, uint32 error_buf_size)
|
||||
{
|
||||
const uint8 *buf_end = buf + size;
|
||||
const uint8 *p = buf, *p_end = buf_end;
|
||||
|
@ -4107,8 +4108,8 @@ load(const uint8 *buf, uint32 size, AOTModule *module, char *error_buf,
|
|||
error_buf_size))
|
||||
return false;
|
||||
|
||||
ret = load_from_sections(module, section_list, true, error_buf,
|
||||
error_buf_size);
|
||||
ret = load_from_sections(module, section_list, !wasm_binary_freeable,
|
||||
error_buf, error_buf_size);
|
||||
if (!ret) {
|
||||
/* If load_from_sections() fails, then aot text is destroyed
|
||||
in destroy_sections() */
|
||||
|
@ -4152,7 +4153,8 @@ aot_load_from_aot_file(const uint8 *buf, uint32 size, const LoadArgs *args,
|
|||
return NULL;
|
||||
|
||||
os_thread_jit_write_protect_np(false); /* Make memory writable */
|
||||
if (!load(buf, size, module, error_buf, error_buf_size)) {
|
||||
if (!load(buf, size, module, args->wasm_binary_freeable, error_buf,
|
||||
error_buf_size)) {
|
||||
aot_unload(module);
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -310,6 +310,9 @@ typedef struct AOTModule {
|
|||
|
||||
/* user defined name */
|
||||
char *name;
|
||||
|
||||
/* Whether the underlying wasm binary buffer can be freed */
|
||||
bool is_binary_freeable;
|
||||
} AOTModule;
|
||||
|
||||
#define AOTMemoryInstance WASMMemoryInstance
|
||||
|
|
|
@ -42,6 +42,8 @@
|
|||
typedef struct wasm_module_ex_t {
|
||||
struct WASMModuleCommon *module_comm_rt;
|
||||
wasm_byte_vec_t *binary;
|
||||
/* If true, binary in wasm_module_ex_t contains a copy of the WASM binary */
|
||||
bool is_binary_cloned;
|
||||
korp_mutex lock;
|
||||
uint32 ref_count;
|
||||
#if WASM_ENABLE_WASM_CACHE != 0
|
||||
|
@ -2242,8 +2244,7 @@ quit:
|
|||
#endif /* WASM_ENABLE_WASM_CACHE != 0 */
|
||||
|
||||
wasm_module_t *
|
||||
wasm_module_new_ex(wasm_store_t *store, const wasm_byte_vec_t *binary,
|
||||
const LoadArgs *args)
|
||||
wasm_module_new_ex(wasm_store_t *store, wasm_byte_vec_t *binary, LoadArgs *args)
|
||||
{
|
||||
char error_buf[128] = { 0 };
|
||||
wasm_module_ex_t *module_ex = NULL;
|
||||
|
@ -2291,6 +2292,8 @@ wasm_module_new_ex(wasm_store_t *store, const wasm_byte_vec_t *binary,
|
|||
if (!module_ex)
|
||||
goto quit;
|
||||
|
||||
module_ex->is_binary_cloned = args->clone_wasm_binary;
|
||||
if (args->clone_wasm_binary) {
|
||||
module_ex->binary = malloc_internal(sizeof(wasm_byte_vec_t));
|
||||
if (!module_ex->binary)
|
||||
goto free_module;
|
||||
|
@ -2298,7 +2301,12 @@ wasm_module_new_ex(wasm_store_t *store, const wasm_byte_vec_t *binary,
|
|||
wasm_byte_vec_copy(module_ex->binary, binary);
|
||||
if (!module_ex->binary->data)
|
||||
goto free_binary;
|
||||
}
|
||||
else {
|
||||
module_ex->binary = binary;
|
||||
}
|
||||
|
||||
args->wasm_binary_freeable = !args->clone_wasm_binary;
|
||||
module_ex->module_comm_rt = wasm_runtime_load_ex(
|
||||
(uint8 *)module_ex->binary->data, (uint32)module_ex->binary->size, args,
|
||||
error_buf, (uint32)sizeof(error_buf));
|
||||
|
@ -2336,8 +2344,10 @@ remove_last:
|
|||
unload:
|
||||
wasm_runtime_unload(module_ex->module_comm_rt);
|
||||
free_vec:
|
||||
if (args->clone_wasm_binary)
|
||||
wasm_byte_vec_delete(module_ex->binary);
|
||||
free_binary:
|
||||
if (args->clone_wasm_binary)
|
||||
wasm_runtime_free(module_ex->binary);
|
||||
free_module:
|
||||
wasm_runtime_free(module_ex);
|
||||
|
@ -2351,7 +2361,8 @@ wasm_module_new(wasm_store_t *store, const wasm_byte_vec_t *binary)
|
|||
{
|
||||
LoadArgs args = { 0 };
|
||||
args.name = "";
|
||||
return wasm_module_new_ex(store, binary, &args);
|
||||
args.clone_wasm_binary = true;
|
||||
return wasm_module_new_ex(store, (wasm_byte_vec_t *)binary, &args);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -2410,6 +2421,7 @@ wasm_module_delete_internal(wasm_module_t *module)
|
|||
return;
|
||||
}
|
||||
|
||||
if (module_ex->is_binary_cloned)
|
||||
DEINIT_VEC(module_ex->binary, wasm_byte_vec_delete);
|
||||
|
||||
if (module_ex->module_comm_rt) {
|
||||
|
@ -2994,6 +3006,16 @@ wasm_module_get_name(wasm_module_t *module)
|
|||
return wasm_runtime_get_module_name(module_ex->module_comm_rt);
|
||||
}
|
||||
|
||||
bool
|
||||
wasm_module_is_underlying_binary_freeable(
|
||||
const wasm_module_t *module, const struct wasm_instance_t *instance)
|
||||
{
|
||||
if (((wasm_module_ex_t *)module)->is_binary_cloned)
|
||||
return true;
|
||||
|
||||
return wasm_runtime_is_underlying_binary_freeable(instance->inst_comm_rt);
|
||||
}
|
||||
|
||||
static wasm_func_t *
|
||||
wasm_func_new_basic(wasm_store_t *store, const wasm_functype_t *type,
|
||||
wasm_func_callback_t func_callback)
|
||||
|
|
|
@ -1350,12 +1350,18 @@ wasm_runtime_load_ex(uint8 *buf, uint32 size, const LoadArgs *args,
|
|||
true,
|
||||
#endif
|
||||
args, error_buf, error_buf_size);
|
||||
if (module_common)
|
||||
((WASMModule *)module_common)->is_binary_freeable =
|
||||
args->wasm_binary_freeable;
|
||||
#endif
|
||||
}
|
||||
else if (get_package_type(buf, size) == Wasm_Module_AoT) {
|
||||
#if WASM_ENABLE_AOT != 0
|
||||
module_common = (WASMModuleCommon *)aot_load_from_aot_file(
|
||||
buf, size, args, error_buf, error_buf_size);
|
||||
if (module_common)
|
||||
((AOTModule *)module_common)->is_binary_freeable =
|
||||
args->wasm_binary_freeable;
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
|
@ -1383,6 +1389,7 @@ wasm_runtime_load(uint8 *buf, uint32 size, char *error_buf,
|
|||
{
|
||||
LoadArgs args = { 0 };
|
||||
args.name = "";
|
||||
args.wasm_binary_freeable = false;
|
||||
return wasm_runtime_load_ex(buf, size, &args, error_buf, error_buf_size);
|
||||
}
|
||||
|
||||
|
@ -1400,6 +1407,7 @@ wasm_runtime_load_from_sections(WASMSection *section_list, bool is_aot,
|
|||
LOG_DEBUG("WASM module load failed from sections");
|
||||
return NULL;
|
||||
}
|
||||
((WASMModule *)module_common)->is_binary_freeable = true;
|
||||
return register_module_with_null_name(module_common, error_buf,
|
||||
error_buf_size);
|
||||
#endif
|
||||
|
@ -1412,6 +1420,7 @@ wasm_runtime_load_from_sections(WASMSection *section_list, bool is_aot,
|
|||
LOG_DEBUG("WASM module load failed from sections");
|
||||
return NULL;
|
||||
}
|
||||
((AOTModule *)module_common)->is_binary_freeable = true;
|
||||
return register_module_with_null_name(module_common, error_buf,
|
||||
error_buf_size);
|
||||
#endif
|
||||
|
@ -7247,3 +7256,51 @@ wasm_runtime_detect_native_stack_overflow_size(WASMExecEnv *exec_env,
|
|||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
WASM_RUNTIME_API_EXTERN bool
|
||||
wasm_runtime_is_underlying_binary_freeable(const wasm_module_inst_t module_inst)
|
||||
{
|
||||
uint32 i;
|
||||
|
||||
#if WASM_ENABLE_INTERP != 0
|
||||
if (module_inst->module_type == Wasm_Module_Bytecode) {
|
||||
#if (WASM_ENABLE_JIT != 0 || WASM_ENABLE_FAST_JIT != 0) \
|
||||
&& (WASM_ENABLE_LAZY_JIT != 0)
|
||||
return false;
|
||||
#elif WASM_ENABLE_FAST_INTERP == 0
|
||||
return false;
|
||||
#else
|
||||
/* Fast interpreter mode */
|
||||
WASMModule *module = ((WASMModuleInstance *)module_inst)->module;
|
||||
if (!module->is_binary_freeable)
|
||||
return false;
|
||||
#if WASM_ENABLE_GC != 0 && WASM_ENABLE_STRINGREF != 0
|
||||
if (module->string_literal_ptrs)
|
||||
return false;
|
||||
#endif
|
||||
#if WASM_ENABLE_BULK_MEMORY != 0
|
||||
for (i = 0; i < module->data_seg_count; i++)
|
||||
if (!bh_bitmap_get_bit(
|
||||
((WASMModuleInstance *)module_inst)->e->common.data_dropped,
|
||||
i))
|
||||
return false;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
#endif /* WASM_ENABLE_INTERP != 0 */
|
||||
#if WASM_ENABLE_AOT != 0
|
||||
if (module_inst->module_type == Wasm_Module_AoT) {
|
||||
AOTModule *module =
|
||||
(AOTModule *)((AOTModuleInstance *)module_inst)->module;
|
||||
if (!module->is_binary_freeable)
|
||||
return false;
|
||||
#if WASM_ENABLE_GC != 0 && WASM_ENABLE_STRINGREF != 0
|
||||
if (module->string_literal_ptrs)
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
#endif /* WASM_ENABLE_AOT != 0 */
|
||||
|
||||
(void)i;
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -1199,6 +1199,10 @@ WASM_RUNTIME_API_EXTERN bool
|
|||
wasm_runtime_detect_native_stack_overflow_size(WASMExecEnv *exec_env,
|
||||
uint32 requested_size);
|
||||
|
||||
WASM_RUNTIME_API_EXTERN bool
|
||||
wasm_runtime_is_underlying_binary_freeable(
|
||||
const wasm_module_inst_t module_inst);
|
||||
|
||||
#if WASM_ENABLE_LINUX_PERF != 0
|
||||
bool
|
||||
wasm_runtime_get_linux_perf(void);
|
||||
|
|
|
@ -528,6 +528,12 @@ typedef struct WASMModuleCommon *wasm_module_t;
|
|||
#define LOAD_ARGS_OPTION_DEFINED
|
||||
typedef struct LoadArgs {
|
||||
char *name;
|
||||
/* True by default, used by wasm-c-api only.
|
||||
If false, the wasm input buffer (wasm_byte_vec_t) is referenced by the
|
||||
module instead of being cloned. Hence, it can be freed after module loading. */
|
||||
bool clone_wasm_binary;
|
||||
/* This option is only used by the AOT/wasm loader (see wasm_export.h) */
|
||||
bool wasm_binary_freeable;
|
||||
/* TODO: more fields? */
|
||||
} LoadArgs;
|
||||
#endif /* LOAD_ARGS_OPTION_DEFINED */
|
||||
|
@ -537,7 +543,7 @@ WASM_API_EXTERN own wasm_module_t* wasm_module_new(
|
|||
|
||||
// please refer to wasm_runtime_load_ex(...) in core/iwasm/include/wasm_export.h
|
||||
WASM_API_EXTERN own wasm_module_t* wasm_module_new_ex(
|
||||
wasm_store_t*, const wasm_byte_vec_t* binary, const LoadArgs *args);
|
||||
wasm_store_t*, wasm_byte_vec_t* binary, LoadArgs *args);
|
||||
|
||||
WASM_API_EXTERN void wasm_module_delete(own wasm_module_t*);
|
||||
|
||||
|
@ -557,6 +563,8 @@ WASM_API_EXTERN void wasm_shared_module_delete(own wasm_shared_module_t*);
|
|||
WASM_API_EXTERN bool wasm_module_set_name(wasm_module_t*, const char* name);
|
||||
WASM_API_EXTERN const char *wasm_module_get_name(wasm_module_t*);
|
||||
|
||||
WASM_API_EXTERN bool wasm_module_is_underlying_binary_freeable(const wasm_module_t *module, const struct wasm_instance_t* instance);
|
||||
|
||||
|
||||
// Function Instances
|
||||
|
||||
|
|
|
@ -227,6 +227,13 @@ typedef struct RuntimeInitArgs {
|
|||
#define LOAD_ARGS_OPTION_DEFINED
|
||||
typedef struct LoadArgs {
|
||||
char *name;
|
||||
/* This option is only used by the Wasm C API (see wasm_c_api.h) */
|
||||
bool clone_wasm_binary;
|
||||
/* False by default, used by AOT/wasm loader only.
|
||||
If true, the AOT/wasm loader creates a copy of some module fields (e.g.
|
||||
const strings), making it possible to free the wasm binary buffer after
|
||||
loading. */
|
||||
bool wasm_binary_freeable;
|
||||
/* TODO: more fields? */
|
||||
} LoadArgs;
|
||||
#endif /* LOAD_ARGS_OPTION_DEFINED */
|
||||
|
@ -1886,6 +1893,16 @@ WASM_RUNTIME_API_EXTERN bool
|
|||
wasm_runtime_detect_native_stack_overflow_size(wasm_exec_env_t exec_env,
|
||||
uint32_t required_size);
|
||||
|
||||
/**
|
||||
* Query whether the wasm binary buffer used to create the module can be freed
|
||||
*
|
||||
* @param module_inst the target module instance
|
||||
* @return true if the wasm binary buffer can be freed
|
||||
*/
|
||||
WASM_RUNTIME_API_EXTERN bool
|
||||
wasm_runtime_is_underlying_binary_freeable(
|
||||
const wasm_module_inst_t module_inst);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1077,6 +1077,9 @@ struct WASMModule {
|
|||
|
||||
/* user defined name */
|
||||
char *name;
|
||||
|
||||
/* Whether the underlying wasm binary buffer can be freed */
|
||||
bool is_binary_freeable;
|
||||
};
|
||||
|
||||
typedef struct BlockType {
|
||||
|
|
|
@ -6120,6 +6120,7 @@ create_module(char *name, char *error_buf, uint32 error_buf_size)
|
|||
module->start_function = (uint32)-1;
|
||||
|
||||
module->name = name;
|
||||
module->is_binary_freeable = false;
|
||||
|
||||
#if WASM_ENABLE_FAST_INTERP == 0
|
||||
module->br_table_cache_list = &module->br_table_cache_list_head;
|
||||
|
@ -6347,8 +6348,8 @@ static union {
|
|||
#define is_little_endian() (__ue.b == 1)
|
||||
|
||||
static bool
|
||||
load(const uint8 *buf, uint32 size, WASMModule *module, char *error_buf,
|
||||
uint32 error_buf_size)
|
||||
load(const uint8 *buf, uint32 size, WASMModule *module,
|
||||
bool wasm_binary_freeable, char *error_buf, uint32 error_buf_size)
|
||||
{
|
||||
const uint8 *buf_end = buf + size;
|
||||
const uint8 *p = buf, *p_end = buf_end;
|
||||
|
@ -6376,8 +6377,8 @@ load(const uint8 *buf, uint32 size, WASMModule *module, char *error_buf,
|
|||
}
|
||||
|
||||
if (!create_sections(buf, size, §ion_list, error_buf, error_buf_size)
|
||||
|| !load_from_sections(module, section_list, true, error_buf,
|
||||
error_buf_size)) {
|
||||
|| !load_from_sections(module, section_list, !wasm_binary_freeable,
|
||||
error_buf, error_buf_size)) {
|
||||
destroy_sections(section_list);
|
||||
return false;
|
||||
}
|
||||
|
@ -6553,7 +6554,8 @@ wasm_loader_load(uint8 *buf, uint32 size,
|
|||
module->load_size = size;
|
||||
#endif
|
||||
|
||||
if (!load(buf, size, module, error_buf, error_buf_size)) {
|
||||
if (!load(buf, size, module, args->wasm_binary_freeable, error_buf,
|
||||
error_buf_size)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
|
|
@ -3008,6 +3008,7 @@ create_module(char *name, char *error_buf, uint32 error_buf_size)
|
|||
module->start_function = (uint32)-1;
|
||||
|
||||
module->name = name;
|
||||
module->is_binary_freeable = false;
|
||||
|
||||
#if WASM_ENABLE_FAST_INTERP == 0
|
||||
module->br_table_cache_list = &module->br_table_cache_list_head;
|
||||
|
@ -3166,8 +3167,8 @@ static union {
|
|||
#define is_little_endian() (__ue.b == 1)
|
||||
|
||||
static bool
|
||||
load(const uint8 *buf, uint32 size, WASMModule *module, char *error_buf,
|
||||
uint32 error_buf_size)
|
||||
load(const uint8 *buf, uint32 size, WASMModule *module,
|
||||
bool wasm_binary_freeable, char *error_buf, uint32 error_buf_size)
|
||||
{
|
||||
const uint8 *buf_end = buf + size;
|
||||
const uint8 *p = buf, *p_end = buf_end;
|
||||
|
@ -3192,8 +3193,8 @@ load(const uint8 *buf, uint32 size, WASMModule *module, char *error_buf,
|
|||
}
|
||||
|
||||
if (!create_sections(buf, size, §ion_list, error_buf, error_buf_size)
|
||||
|| !load_from_sections(module, section_list, true, error_buf,
|
||||
error_buf_size)) {
|
||||
|| !load_from_sections(module, section_list, !wasm_binary_freeable,
|
||||
error_buf, error_buf_size)) {
|
||||
destroy_sections(section_list);
|
||||
return false;
|
||||
}
|
||||
|
@ -3218,7 +3219,8 @@ wasm_loader_load(uint8 *buf, uint32 size, const LoadArgs *args, char *error_buf,
|
|||
module->load_size = size;
|
||||
#endif
|
||||
|
||||
if (!load(buf, size, module, error_buf, error_buf_size)) {
|
||||
if (!load(buf, size, module, args->wasm_binary_freeable, error_buf,
|
||||
error_buf_size)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
|
|
@ -30,3 +30,5 @@ Normally there are some methods to tune the memory usage:
|
|||
- set the app heap size with `wasm_runtime_instantiate`
|
||||
- use `nostdlib` mode, add `-Wl,--strip-all`: refer to [How to reduce the footprint](./build_wasm_app.md#2-how-to-reduce-the-footprint) of building wasm app for more details
|
||||
- use XIP mode, refer to [WAMR XIP (Execution In Place) feature introduction](./xip.md) for more details
|
||||
- when using the Wasm C API in fast interpreter or AOT mode, set `clone_wasm_binary=false` in `LoadArgs` and free the wasm binary buffer (with `wasm_byte_vec_delete`) after module loading; `wasm_module_is_underlying_binary_freeable` can be queried to check if the wasm binary buffer can be safely freed (see [the example](../samples/basic/src/free_buffer_early.c)); after the buffer is freed, `wasm_runtime_get_custom_section` cannot be called anymore
|
||||
- when using the wasm/AOT loader in fast interpreter or AOT mode, set `wasm_binary_freeable=true` in `LoadArgs` and free the wasm binary buffer (with `wasm_byte_vec_delete`) after module loading; `wasm_runtime_is_underlying_binary_freeable` can be queried to check if the wasm binary buffer can be safely freed; after the buffer is freed, `wasm_runtime_get_custom_section` cannot be called anymore
|
||||
|
|
|
@ -79,12 +79,16 @@ include_directories(${CMAKE_CURRENT_LIST_DIR}/src)
|
|||
include (${SHARED_DIR}/utils/uncommon/shared_uncommon.cmake)
|
||||
|
||||
add_executable (basic src/main.c src/native_impl.c ${UNCOMMON_SHARED_SOURCE})
|
||||
add_executable (free_buffer_early src/free_buffer_early.c ${UNCOMMON_SHARED_SOURCE})
|
||||
|
||||
check_pie_supported()
|
||||
set_target_properties (basic PROPERTIES POSITION_INDEPENDENT_CODE ON)
|
||||
set_target_properties (free_buffer_early PROPERTIES POSITION_INDEPENDENT_CODE ON)
|
||||
|
||||
if (APPLE)
|
||||
target_link_libraries (basic vmlib -lm -ldl -lpthread)
|
||||
target_link_libraries (free_buffer_early vmlib -lm -ldl -lpthread)
|
||||
else ()
|
||||
target_link_libraries (basic vmlib -lm -ldl -lpthread -lrt)
|
||||
target_link_libraries (free_buffer_early vmlib -lm -ldl -lpthread -lrt)
|
||||
endif ()
|
||||
|
|
|
@ -50,6 +50,7 @@ OUT_FILE=${i%.*}.wasm
|
|||
-Wl,--export=generate_float \
|
||||
-Wl,--export=float_to_string \
|
||||
-Wl,--export=calculate\
|
||||
-Wl,--export=mul7\
|
||||
-Wl,--allow-undefined \
|
||||
-o ${OUT_DIR}/wasm-apps/${OUT_FILE} ${APP_SRC}
|
||||
|
||||
|
|
121
samples/basic/src/free_buffer_early.c
Normal file
121
samples/basic/src/free_buffer_early.c
Normal file
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
* Copyright (C) 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#include "wasm_export.h"
|
||||
#include "bh_read_file.h"
|
||||
|
||||
void
|
||||
my_log(uint32 log_level, const char *file, int line, const char *fmt, ...)
|
||||
{
|
||||
char buf[200];
|
||||
snprintf(buf, sizeof(buf), "[WamrLogger] %s\n", fmt);
|
||||
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
vprintf(buf, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
int
|
||||
my_vprintf(const char *format, va_list ap)
|
||||
{
|
||||
return vprintf(format, ap);
|
||||
}
|
||||
|
||||
void
|
||||
print_usage(void)
|
||||
{
|
||||
fprintf(stdout, "Options:\r\n");
|
||||
fprintf(stdout, " -f [path of wasm file] \n");
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv_main[])
|
||||
{
|
||||
static char global_heap_buf[512 * 1024];
|
||||
char *buffer = NULL, error_buf[128];
|
||||
int opt;
|
||||
char *wasm_path = NULL;
|
||||
bool success;
|
||||
|
||||
wasm_module_t module = NULL;
|
||||
wasm_module_inst_t module_inst = NULL;
|
||||
uint32 buf_size, stack_size = 8092, heap_size = 8092;
|
||||
LoadArgs load_args = { 0 };
|
||||
|
||||
RuntimeInitArgs init_args;
|
||||
memset(&init_args, 0, sizeof(RuntimeInitArgs));
|
||||
|
||||
while ((opt = getopt(argc, argv_main, "hf:")) != -1) {
|
||||
switch (opt) {
|
||||
case 'f':
|
||||
wasm_path = optarg;
|
||||
break;
|
||||
case 'h':
|
||||
print_usage();
|
||||
return 0;
|
||||
case '?':
|
||||
print_usage();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (optind == 1) {
|
||||
print_usage();
|
||||
return 0;
|
||||
}
|
||||
|
||||
init_args.mem_alloc_type = Alloc_With_Pool;
|
||||
init_args.mem_alloc_option.pool.heap_buf = global_heap_buf;
|
||||
init_args.mem_alloc_option.pool.heap_size = sizeof(global_heap_buf);
|
||||
|
||||
if (!wasm_runtime_full_init(&init_args)) {
|
||||
printf("Init runtime environment failed.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
buffer = bh_read_file_to_buffer(wasm_path, &buf_size);
|
||||
if (!buffer) {
|
||||
printf("Open wasm app file [%s] failed.\n", wasm_path);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
load_args.wasm_binary_freeable = true;
|
||||
module = wasm_runtime_load_ex((uint8 *)buffer, buf_size, &load_args,
|
||||
error_buf, sizeof(error_buf));
|
||||
if (!module) {
|
||||
printf("Load wasm module failed. error: %s\n", error_buf);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
module_inst = wasm_runtime_instantiate(module, stack_size, heap_size,
|
||||
error_buf, sizeof(error_buf));
|
||||
if (!module_inst) {
|
||||
printf("Instantiate wasm module failed. error: %s.\n", error_buf);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (wasm_runtime_is_underlying_binary_freeable(module_inst)) {
|
||||
printf("Able to free wasm binary buffer.\n");
|
||||
wasm_runtime_free(buffer);
|
||||
buffer = NULL;
|
||||
}
|
||||
|
||||
char *args[1] = { "3" };
|
||||
success = wasm_application_execute_func(module_inst, "mul7", 1, args);
|
||||
if (!success) {
|
||||
printf("Unable to execute function.\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
fail:
|
||||
if (module_inst)
|
||||
wasm_runtime_deinstantiate(module_inst);
|
||||
if (module)
|
||||
wasm_runtime_unload(module);
|
||||
if (buffer)
|
||||
wasm_runtime_free(buffer);
|
||||
wasm_runtime_destroy();
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user