Skip to content

Commit 382357c

Browse files
authored
Implement wasm module serialize and deserialize (#1485)
Decide to use the .aot content as the .wasm precompiled result: - `wasm_module_serialize(...)` will return it - `wasm_module_deserialize(...)` will load the precompiled content as normal .aot file
1 parent 1af870b commit 382357c

File tree

7 files changed

+207
-5
lines changed

7 files changed

+207
-5
lines changed

.gitignore

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,7 @@ tests/wamr-test-suites/workspace
2727

2828
samples/socket-api/wasm-src/inc/pthread.h
2929

30-
**/__pycache__
30+
**/__pycache__
31+
32+
# ignore benchmarks generated
33+
tests/benchmarks/coremark/coremark*

core/iwasm/common/wasm_c_api.c

Lines changed: 62 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,20 @@
22
* Copyright (C) 2019 Intel Corporation. All rights reserved.
33
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
44
*/
5-
65
#include "wasm_c_api_internal.h"
6+
7+
#include "bh_assert.h"
78
#include "wasm_memory.h"
8-
#include "wasm_runtime_common.h"
99
#if WASM_ENABLE_INTERP != 0
1010
#include "wasm_runtime.h"
1111
#endif
1212
#if WASM_ENABLE_AOT != 0
1313
#include "aot_runtime.h"
14-
#endif
14+
#if WASM_ENABLE_JIT != 0 && WASM_ENABLE_LAZY_JIT == 0
15+
#include "aot.h"
16+
#include "aot_llvm.h"
17+
#endif /*WASM_ENABLE_JIT != 0 && WASM_ENABLE_LAZY_JIT == 0*/
18+
#endif /*WASM_ENABLE_AOT != 0*/
1519

1620
#define ASSERT_NOT_IMPLEMENTED() bh_assert(!"not implemented")
1721
#define UNREACHABLE() bh_assert(!"unreachable")
@@ -2379,6 +2383,61 @@ wasm_module_exports(const wasm_module_t *module, wasm_exporttype_vec_t *out)
23792383
wasm_exporttype_vec_delete(out);
23802384
}
23812385

2386+
#if WASM_ENABLE_JIT == 0 || WASM_ENABLE_LAZY_JIT != 0
2387+
void
2388+
wasm_module_serialize(wasm_module_t *module, own wasm_byte_vec_t *out)
2389+
{
2390+
(void)module;
2391+
(void)out;
2392+
LOG_ERROR("only supported serialization in JIT with eager compilation");
2393+
}
2394+
2395+
own wasm_module_t *
2396+
wasm_module_deserialize(wasm_store_t *module, const wasm_byte_vec_t *binary)
2397+
{
2398+
(void)module;
2399+
(void)binary;
2400+
LOG_ERROR("only supported deserialization in JIT with eager compilation");
2401+
return NULL;
2402+
}
2403+
#else
2404+
2405+
extern uint8 *
2406+
aot_emit_aot_file_buf(AOTCompContext *comp_ctx, AOTCompData *comp_data,
2407+
uint32 *p_aot_file_size);
2408+
void
2409+
wasm_module_serialize(wasm_module_t *module, own wasm_byte_vec_t *out)
2410+
{
2411+
wasm_module_ex_t *module_ex;
2412+
AOTCompContext *comp_ctx;
2413+
AOTCompData *comp_data;
2414+
uint8 *aot_file_buf = NULL;
2415+
uint32 aot_file_size = 0;
2416+
2417+
if (!module || !out)
2418+
return;
2419+
2420+
module_ex = module_to_module_ext(module);
2421+
comp_ctx = ((WASMModule *)(module_ex->module_comm_rt))->comp_ctx;
2422+
comp_data = ((WASMModule *)(module_ex->module_comm_rt))->comp_data;
2423+
bh_assert(comp_ctx != NULL && comp_data != NULL);
2424+
2425+
aot_file_buf = aot_emit_aot_file_buf(comp_ctx, comp_data, &aot_file_size);
2426+
if (!aot_file_buf)
2427+
return;
2428+
2429+
wasm_byte_vec_new(out, aot_file_size, (wasm_byte_t *)aot_file_buf);
2430+
wasm_runtime_free(aot_file_buf);
2431+
return;
2432+
}
2433+
2434+
own wasm_module_t *
2435+
wasm_module_deserialize(wasm_store_t *store, const wasm_byte_vec_t *binary)
2436+
{
2437+
return wasm_module_new(store, binary);
2438+
}
2439+
#endif
2440+
23822441
static wasm_func_t *
23832442
wasm_func_new_basic(wasm_store_t *store, const wasm_functype_t *type,
23842443
wasm_func_callback_t func_callback)

core/iwasm/include/wasm_c_api.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -461,7 +461,7 @@ WASM_API_EXTERN bool wasm_module_validate(wasm_store_t*, const wasm_byte_vec_t*
461461
WASM_API_EXTERN void wasm_module_imports(const wasm_module_t*, own wasm_importtype_vec_t* out);
462462
WASM_API_EXTERN void wasm_module_exports(const wasm_module_t*, own wasm_exporttype_vec_t* out);
463463

464-
WASM_API_EXTERN void wasm_module_serialize(const wasm_module_t*, own wasm_byte_vec_t* out);
464+
WASM_API_EXTERN void wasm_module_serialize(wasm_module_t*, own wasm_byte_vec_t* out);
465465
WASM_API_EXTERN own wasm_module_t* wasm_module_deserialize(wasm_store_t*, const wasm_byte_vec_t*);
466466

467467

core/iwasm/interpreter/wasm_runtime.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3321,6 +3321,7 @@ fast_jit_call_indirect(WASMExecEnv *exec_env, uint32 tbl_idx, uint32 elem_idx,
33213321
#endif
33223322

33233323
#if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0
3324+
33243325
bool
33253326
llvm_jit_call_indirect(WASMExecEnv *exec_env, uint32 tbl_idx, uint32 elem_idx,
33263327
uint32 argc, uint32 *argv)

samples/wasm-c-api/CMakeLists.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,12 @@ set(EXAMPLES
135135
trap
136136
)
137137

138+
if(WAMR_BUILD_JIT AND WAMR_BUILD_LAZY_JIT)
139+
if((${WAMR_BUILD_JIT} EQUAL 1) AND (${WAMR_BUILD_LAZY_JIT} EQUAL 1))
140+
list(APPEND EXAMPLES serialize)
141+
endif()
142+
endif()
143+
138144
foreach(EX ${EXAMPLES})
139145
set(SRC ${CMAKE_CURRENT_LIST_DIR}/src/${EX}.c)
140146

samples/wasm-c-api/src/serialize.c

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
#include <stdio.h>
2+
#include <stdlib.h>
3+
#include <string.h>
4+
#include <inttypes.h>
5+
6+
#include "wasm_c_api.h"
7+
8+
#define own
9+
10+
// A function to be called from Wasm code.
11+
own wasm_trap_t *
12+
hello_callback(const wasm_val_vec_t *args, wasm_val_vec_t *results)
13+
{
14+
printf("Calling back...\n");
15+
printf("> Hello World!\n");
16+
return NULL;
17+
}
18+
19+
int
20+
main(int argc, const char *argv[])
21+
{
22+
// Initialize.
23+
printf("Initializing...\n");
24+
wasm_engine_t *engine = wasm_engine_new();
25+
wasm_store_t *store = wasm_store_new(engine);
26+
27+
// Load binary.
28+
printf("Loading binary...\n");
29+
FILE *file = fopen("serialize.wasm", "rb");
30+
if (!file) {
31+
printf("> Error loading module!\n");
32+
return 1;
33+
}
34+
fseek(file, 0L, SEEK_END);
35+
size_t file_size = ftell(file);
36+
fseek(file, 0L, SEEK_SET);
37+
wasm_byte_vec_t binary;
38+
wasm_byte_vec_new_uninitialized(&binary, file_size);
39+
if (fread(binary.data, file_size, 1, file) != 1) {
40+
printf("> Error loading module!\n");
41+
return 1;
42+
}
43+
fclose(file);
44+
45+
// Compile.
46+
printf("Compiling module...\n");
47+
own wasm_module_t *module = wasm_module_new(store, &binary);
48+
if (!module) {
49+
printf("> Error compiling module!\n");
50+
return 1;
51+
}
52+
53+
wasm_byte_vec_delete(&binary);
54+
55+
// Serialize module.
56+
printf("Serializing module...\n");
57+
own wasm_byte_vec_t serialized;
58+
wasm_module_serialize(module, &serialized);
59+
60+
wasm_module_delete(module);
61+
62+
// Deserialize module.
63+
printf("Deserializing module...\n");
64+
own wasm_module_t *deserialized =
65+
wasm_module_deserialize(store, &serialized);
66+
if (!deserialized) {
67+
printf("> Error deserializing module!\n");
68+
return 1;
69+
}
70+
71+
wasm_byte_vec_delete(&serialized);
72+
73+
// Create external print functions.
74+
printf("Creating callback...\n");
75+
own wasm_functype_t *hello_type = wasm_functype_new_0_0();
76+
own wasm_func_t *hello_func =
77+
wasm_func_new(store, hello_type, hello_callback);
78+
79+
wasm_functype_delete(hello_type);
80+
81+
// Instantiate.
82+
printf("Instantiating deserialized module...\n");
83+
wasm_extern_t *externs[] = { wasm_func_as_extern(hello_func) };
84+
wasm_extern_vec_t imports = WASM_ARRAY_VEC(externs);
85+
own wasm_instance_t *instance =
86+
wasm_instance_new(store, deserialized, &imports, NULL);
87+
if (!instance) {
88+
printf("> Error instantiating module!\n");
89+
return 1;
90+
}
91+
92+
wasm_func_delete(hello_func);
93+
94+
// Extract export.
95+
printf("Extracting export...\n");
96+
own wasm_extern_vec_t exports;
97+
wasm_instance_exports(instance, &exports);
98+
if (exports.size == 0) {
99+
printf("> Error accessing exports!\n");
100+
return 1;
101+
}
102+
const wasm_func_t *run_func = wasm_extern_as_func(exports.data[0]);
103+
if (run_func == NULL) {
104+
printf("> Error accessing export!\n");
105+
return 1;
106+
}
107+
108+
wasm_module_delete(deserialized);
109+
wasm_instance_delete(instance);
110+
111+
// Call.
112+
printf("Calling export...\n");
113+
wasm_val_vec_t empty = WASM_EMPTY_VEC;
114+
if (wasm_func_call(run_func, &empty, &empty)) {
115+
printf("> Error calling function!\n");
116+
return 1;
117+
}
118+
119+
wasm_extern_vec_delete(&exports);
120+
121+
// Shut down.
122+
printf("Shutting down...\n");
123+
wasm_store_delete(store);
124+
wasm_engine_delete(engine);
125+
126+
// All done.
127+
printf("Done.\n");
128+
return 0;
129+
}

samples/wasm-c-api/src/serialize.wat

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
(module
2+
(func $hello (import "" "hello"))
3+
(func (export "run") (call $hello))
4+
)

0 commit comments

Comments
 (0)