Skip to content

Commit

Permalink
feat(wasm-c-api): allow not copying the wasm binary into the module
Browse files Browse the repository at this point in the history
  • Loading branch information
eloparco committed May 8, 2024
1 parent c0e33f0 commit 56a4f5d
Show file tree
Hide file tree
Showing 6 changed files with 51 additions and 24 deletions.
11 changes: 6 additions & 5 deletions core/iwasm/aot/aot_loader.c
Original file line number Diff line number Diff line change
Expand Up @@ -4065,8 +4065,8 @@ create_sections(AOTModule *module, const uint8 *buf, uint32 size,
}

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;
Expand All @@ -4090,8 +4090,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() */
Expand Down Expand Up @@ -4135,7 +4135,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;
}
Expand Down
35 changes: 24 additions & 11 deletions core/iwasm/common/wasm_c_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -2234,7 +2236,7 @@ try_reuse_loaded_module(wasm_store_t *store, char *binary_hash)
#endif /* WASM_ENABLE_WASM_CACHE != 0 */

wasm_module_t *
wasm_module_new_ex(wasm_store_t *store, const wasm_byte_vec_t *binary,
wasm_module_new_ex(wasm_store_t *store, wasm_byte_vec_t *binary,
const LoadArgs *args)
{
char error_buf[128] = { 0 };
Expand Down Expand Up @@ -2283,13 +2285,19 @@ wasm_module_new_ex(wasm_store_t *store, const wasm_byte_vec_t *binary,
if (!module_ex)
goto quit;

module_ex->binary = malloc_internal(sizeof(wasm_byte_vec_t));
if (!module_ex->binary)
goto free_module;
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;

wasm_byte_vec_copy(module_ex->binary, binary);
if (!module_ex->binary->data)
goto free_binary;
wasm_byte_vec_copy(module_ex->binary, binary);
if (!module_ex->binary->data)
goto free_binary;
}
else {
module_ex->binary = binary;
}

module_ex->module_comm_rt = wasm_runtime_load_ex(
(uint8 *)module_ex->binary->data, (uint32)module_ex->binary->size, args,
Expand Down Expand Up @@ -2328,9 +2336,11 @@ wasm_module_new_ex(wasm_store_t *store, const wasm_byte_vec_t *binary,
unload:
wasm_runtime_unload(module_ex->module_comm_rt);
free_vec:
wasm_byte_vec_delete(module_ex->binary);
if (args->clone_wasm_binary)
wasm_byte_vec_delete(module_ex->binary);
free_binary:
wasm_runtime_free(module_ex->binary);
if (args->clone_wasm_binary)
wasm_runtime_free(module_ex->binary);
free_module:
wasm_runtime_free(module_ex);
quit:
Expand All @@ -2343,7 +2353,9 @@ 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;
args.wasm_binary_freeable = false;
return wasm_module_new_ex(store, (wasm_byte_vec_t *)binary, &args);
}

bool
Expand Down Expand Up @@ -2402,7 +2414,8 @@ wasm_module_delete_internal(wasm_module_t *module)
return;
}

DEINIT_VEC(module_ex->binary, wasm_byte_vec_delete);
if (module_ex->is_binary_cloned)
DEINIT_VEC(module_ex->binary, wasm_byte_vec_delete);

if (module_ex->module_comm_rt) {
wasm_runtime_unload(module_ex->module_comm_rt);
Expand Down
13 changes: 10 additions & 3 deletions core/iwasm/include/wasm_c_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -527,16 +527,23 @@ 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;
/* False by default, used by wasm-c-api 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 */

WASM_API_EXTERN own wasm_module_t* wasm_module_new(
wasm_store_t*, const wasm_byte_vec_t* binary);
WASM_API_EXTERN own wasm_module_t* wasm_module_new(wasm_store_t*, const wasm_byte_vec_t* binary);

// 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, const LoadArgs *args);

WASM_API_EXTERN void wasm_module_delete(own wasm_module_t*);

Expand Down
4 changes: 4 additions & 0 deletions core/iwasm/include/wasm_export.h
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,10 @@ 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;
/* This option is only used by the Wasm C API (see wasm_c_api.h) */
bool wasm_binary_freeable;
/* TODO: more fields? */
} LoadArgs;
#endif /* LOAD_ARGS_OPTION_DEFINED */
Expand Down
11 changes: 6 additions & 5 deletions core/iwasm/interpreter/wasm_loader.c
Original file line number Diff line number Diff line change
Expand Up @@ -6376,8 +6376,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;
Expand Down Expand Up @@ -6405,8 +6405,8 @@ load(const uint8 *buf, uint32 size, WASMModule *module, char *error_buf,
}

if (!create_sections(buf, size, &section_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;
}
Expand Down Expand Up @@ -6582,7 +6582,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;
}

Expand Down
1 change: 1 addition & 0 deletions doc/memory_tune.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,4 @@ 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, set `clone_wasm_binary=false` and `wasm_binary_freeable=true` in `LoadArgs` and free the wasm binary buffer (with `wasm_byte_vec_delete`) after module loading

0 comments on commit 56a4f5d

Please sign in to comment.