Skip to content

Commit 4ef724b

Browse files
authored
Enhance wasm loading with LoadArgs and support module names (#3265)
- Add new API wasm_runtime_load_ex() in wasm_export.h and wasm_module_new_ex in wasm_c_api.h - Put aot_create_perf_map() into a separated file aot_perf_map.c - In perf.map, function names include user specified module name - Enhance the script to help flamegraph generations
1 parent cee9b82 commit 4ef724b

28 files changed

+3008
-346
lines changed

core/iwasm/aot/aot_loader.c

+11-105
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@
1616
#include "debug/jit_debug.h"
1717
#endif
1818

19+
#if WASM_ENABLE_LINUX_PERF != 0
20+
#include "aot_perf_map.h"
21+
#endif
22+
1923
#define YMM_PLT_PREFIX "__ymm@"
2024
#define XMM_PLT_PREFIX "__xmm@"
2125
#define REAL_PLT_PREFIX "__real@"
@@ -3601,104 +3605,6 @@ load_relocation_section(const uint8 *buf, const uint8 *buf_end,
36013605
return ret;
36023606
}
36033607

3604-
#if WASM_ENABLE_LINUX_PERF != 0
3605-
struct func_info {
3606-
uint32 idx;
3607-
void *ptr;
3608-
};
3609-
3610-
static uint32
3611-
get_func_size(const AOTModule *module, struct func_info *sorted_func_ptrs,
3612-
uint32 idx)
3613-
{
3614-
uint32 func_sz;
3615-
3616-
if (idx == module->func_count - 1)
3617-
func_sz = (uintptr_t)module->code + module->code_size
3618-
- (uintptr_t)(sorted_func_ptrs[idx].ptr);
3619-
else
3620-
func_sz = (uintptr_t)(sorted_func_ptrs[idx + 1].ptr)
3621-
- (uintptr_t)(sorted_func_ptrs[idx].ptr);
3622-
3623-
return func_sz;
3624-
}
3625-
3626-
static int
3627-
compare_func_ptrs(const void *f1, const void *f2)
3628-
{
3629-
return (intptr_t)((struct func_info *)f1)->ptr
3630-
- (intptr_t)((struct func_info *)f2)->ptr;
3631-
}
3632-
3633-
static struct func_info *
3634-
sort_func_ptrs(const AOTModule *module, char *error_buf, uint32 error_buf_size)
3635-
{
3636-
uint64 content_len;
3637-
struct func_info *sorted_func_ptrs;
3638-
unsigned i;
3639-
3640-
content_len = (uint64)sizeof(struct func_info) * module->func_count;
3641-
sorted_func_ptrs = loader_malloc(content_len, error_buf, error_buf_size);
3642-
if (!sorted_func_ptrs)
3643-
return NULL;
3644-
3645-
for (i = 0; i < module->func_count; i++) {
3646-
sorted_func_ptrs[i].idx = i;
3647-
sorted_func_ptrs[i].ptr = module->func_ptrs[i];
3648-
}
3649-
3650-
qsort(sorted_func_ptrs, module->func_count, sizeof(struct func_info),
3651-
compare_func_ptrs);
3652-
3653-
return sorted_func_ptrs;
3654-
}
3655-
3656-
static bool
3657-
create_perf_map(const AOTModule *module, char *error_buf, uint32 error_buf_size)
3658-
{
3659-
struct func_info *sorted_func_ptrs = NULL;
3660-
char perf_map_info[128] = { 0 };
3661-
FILE *perf_map = NULL;
3662-
uint32 i;
3663-
pid_t pid = getpid();
3664-
bool ret = false;
3665-
3666-
sorted_func_ptrs = sort_func_ptrs(module, error_buf, error_buf_size);
3667-
if (!sorted_func_ptrs)
3668-
goto quit;
3669-
3670-
snprintf(perf_map_info, 128, "/tmp/perf-%d.map", pid);
3671-
perf_map = fopen(perf_map_info, "w");
3672-
if (!perf_map) {
3673-
LOG_WARNING("warning: can't create /tmp/perf-%d.map, because %s", pid,
3674-
strerror(errno));
3675-
goto quit;
3676-
}
3677-
3678-
for (i = 0; i < module->func_count; i++) {
3679-
memset(perf_map_info, 0, 128);
3680-
snprintf(perf_map_info, 128, "%lx %x aot_func#%u\n",
3681-
(uintptr_t)sorted_func_ptrs[i].ptr,
3682-
get_func_size(module, sorted_func_ptrs, i),
3683-
sorted_func_ptrs[i].idx);
3684-
3685-
fwrite(perf_map_info, 1, strlen(perf_map_info), perf_map);
3686-
}
3687-
3688-
LOG_VERBOSE("generate /tmp/perf-%d.map", pid);
3689-
ret = true;
3690-
3691-
quit:
3692-
if (sorted_func_ptrs)
3693-
free(sorted_func_ptrs);
3694-
3695-
if (perf_map)
3696-
fclose(perf_map);
3697-
3698-
return ret;
3699-
}
3700-
#endif /* WASM_ENABLE_LINUX_PERF != 0*/
3701-
37023608
static bool
37033609
load_from_sections(AOTModule *module, AOTSection *sections,
37043610
bool is_load_from_file_buf, char *error_buf,
@@ -3889,7 +3795,7 @@ load_from_sections(AOTModule *module, AOTSection *sections,
38893795
}
38903796

38913797
static AOTModule *
3892-
create_module(char *error_buf, uint32 error_buf_size)
3798+
create_module(char *name, char *error_buf, uint32 error_buf_size)
38933799
{
38943800
AOTModule *module =
38953801
loader_malloc(sizeof(AOTModule), error_buf, error_buf_size);
@@ -3901,7 +3807,7 @@ create_module(char *error_buf, uint32 error_buf_size)
39013807

39023808
module->module_type = Wasm_Module_AoT;
39033809

3904-
module->name = "";
3810+
module->name = name;
39053811

39063812
#if WASM_ENABLE_MULTI_MODULE != 0
39073813
module->import_module_list = &module->import_module_list_head;
@@ -3937,7 +3843,7 @@ AOTModule *
39373843
aot_load_from_sections(AOTSection *section_list, char *error_buf,
39383844
uint32 error_buf_size)
39393845
{
3940-
AOTModule *module = create_module(error_buf, error_buf_size);
3846+
AOTModule *module = create_module("", error_buf, error_buf_size);
39413847

39423848
if (!module)
39433849
return NULL;
@@ -4183,7 +4089,7 @@ load(const uint8 *buf, uint32 size, AOTModule *module, char *error_buf,
41834089

41844090
#if WASM_ENABLE_LINUX_PERF != 0
41854091
if (wasm_runtime_get_linux_perf())
4186-
if (!create_perf_map(module, error_buf, error_buf_size))
4092+
if (!aot_create_perf_map(module, error_buf, error_buf_size))
41874093
goto fail;
41884094
#endif
41894095

@@ -4193,10 +4099,10 @@ load(const uint8 *buf, uint32 size, AOTModule *module, char *error_buf,
41934099
}
41944100

41954101
AOTModule *
4196-
aot_load_from_aot_file(const uint8 *buf, uint32 size, char *error_buf,
4197-
uint32 error_buf_size)
4102+
aot_load_from_aot_file(const uint8 *buf, uint32 size, const LoadArgs *args,
4103+
char *error_buf, uint32 error_buf_size)
41984104
{
4199-
AOTModule *module = create_module(error_buf, error_buf_size);
4105+
AOTModule *module = create_module(args->name, error_buf, error_buf_size);
42004106

42014107
if (!module)
42024108
return NULL;

core/iwasm/aot/aot_perf_map.c

+120
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
/*
2+
* Copyright (C) 2019 Intel Corporation. All rights reserved.
3+
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
4+
*/
5+
6+
#include "aot_perf_map.h"
7+
#include "bh_log.h"
8+
#include "bh_platform.h"
9+
10+
#if WASM_ENABLE_LINUX_PERF != 0
11+
struct func_info {
12+
uint32 idx;
13+
void *ptr;
14+
};
15+
16+
static uint32
17+
get_func_size(const AOTModule *module, struct func_info *sorted_func_ptrs,
18+
uint32 idx)
19+
{
20+
uint32 func_sz;
21+
22+
if (idx == module->func_count - 1)
23+
func_sz = (uintptr_t)module->code + module->code_size
24+
- (uintptr_t)(sorted_func_ptrs[idx].ptr);
25+
else
26+
func_sz = (uintptr_t)(sorted_func_ptrs[idx + 1].ptr)
27+
- (uintptr_t)(sorted_func_ptrs[idx].ptr);
28+
29+
return func_sz;
30+
}
31+
32+
static int
33+
compare_func_ptrs(const void *f1, const void *f2)
34+
{
35+
return (intptr_t)((struct func_info *)f1)->ptr
36+
- (intptr_t)((struct func_info *)f2)->ptr;
37+
}
38+
39+
static struct func_info *
40+
sort_func_ptrs(const AOTModule *module, char *error_buf, uint32 error_buf_size)
41+
{
42+
uint64 content_len;
43+
struct func_info *sorted_func_ptrs;
44+
unsigned i;
45+
46+
content_len = (uint64)sizeof(struct func_info) * module->func_count;
47+
sorted_func_ptrs = wasm_runtime_malloc(content_len);
48+
if (!sorted_func_ptrs) {
49+
snprintf(error_buf, error_buf_size,
50+
"allocate memory failed when creating perf map");
51+
return NULL;
52+
}
53+
54+
for (i = 0; i < module->func_count; i++) {
55+
sorted_func_ptrs[i].idx = i;
56+
sorted_func_ptrs[i].ptr = module->func_ptrs[i];
57+
}
58+
59+
qsort(sorted_func_ptrs, module->func_count, sizeof(struct func_info),
60+
compare_func_ptrs);
61+
62+
return sorted_func_ptrs;
63+
}
64+
65+
bool
66+
aot_create_perf_map(const AOTModule *module, char *error_buf,
67+
uint32 error_buf_size)
68+
{
69+
struct func_info *sorted_func_ptrs = NULL;
70+
char perf_map_path[64] = { 0 };
71+
char perf_map_info[128] = { 0 };
72+
FILE *perf_map = NULL;
73+
uint32 i;
74+
pid_t pid = getpid();
75+
bool ret = false;
76+
77+
sorted_func_ptrs = sort_func_ptrs(module, error_buf, error_buf_size);
78+
if (!sorted_func_ptrs)
79+
goto quit;
80+
81+
snprintf(perf_map_path, sizeof(perf_map_path) - 1, "/tmp/perf-%d.map", pid);
82+
perf_map = fopen(perf_map_path, "a");
83+
if (!perf_map) {
84+
LOG_WARNING("warning: can't create /tmp/perf-%d.map, because %s", pid,
85+
strerror(errno));
86+
goto quit;
87+
}
88+
89+
const char *module_name = aot_get_module_name((AOTModule *)module);
90+
for (i = 0; i < module->func_count; i++) {
91+
memset(perf_map_info, 0, 128);
92+
if (strlen(module_name) > 0)
93+
snprintf(perf_map_info, 128, "%lx %x [%s]#aot_func#%u\n",
94+
(uintptr_t)sorted_func_ptrs[i].ptr,
95+
get_func_size(module, sorted_func_ptrs, i), module_name,
96+
sorted_func_ptrs[i].idx);
97+
else
98+
snprintf(perf_map_info, 128, "%lx %x aot_func#%u\n",
99+
(uintptr_t)sorted_func_ptrs[i].ptr,
100+
get_func_size(module, sorted_func_ptrs, i),
101+
sorted_func_ptrs[i].idx);
102+
103+
/* fwrite() is thread safe */
104+
fwrite(perf_map_info, 1, strlen(perf_map_info), perf_map);
105+
}
106+
107+
LOG_VERBOSE("write map information from %s into /tmp/perf-%d.map",
108+
module_name, pid);
109+
ret = true;
110+
111+
quit:
112+
if (sorted_func_ptrs)
113+
wasm_runtime_free(sorted_func_ptrs);
114+
115+
if (perf_map)
116+
fclose(perf_map);
117+
118+
return ret;
119+
}
120+
#endif /* WASM_ENABLE_LINUX_PERF != 0 */

core/iwasm/aot/aot_perf_map.h

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/*
2+
* Copyright (C) 2019 Intel Corporation. All rights reserved.
3+
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
4+
*/
5+
6+
#ifndef _AOT_PERF_MAP_H_
7+
#define _AOT_PERF_MAP_H_
8+
9+
#include "aot_runtime.h"
10+
11+
bool
12+
aot_create_perf_map(const AOTModule *module, char *error_buf,
13+
uint32 error_buf_size);
14+
15+
#endif /* _AOT_PERF_MAP_H_ */

core/iwasm/aot/aot_runtime.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -444,8 +444,8 @@ typedef struct LLVMProfileData_64 {
444444
* @return return AOT module loaded, NULL if failed
445445
*/
446446
AOTModule *
447-
aot_load_from_aot_file(const uint8 *buf, uint32 size, char *error_buf,
448-
uint32 error_buf_size);
447+
aot_load_from_aot_file(const uint8 *buf, uint32 size, const LoadArgs *args,
448+
char *error_buf, uint32 error_buf_size);
449449

450450
/**
451451
* Load a AOT module from a specified AOT section list.

core/iwasm/common/wasm_c_api.c

+12-3
Original file line numberDiff line numberDiff line change
@@ -2234,7 +2234,8 @@ try_reuse_loaded_module(wasm_store_t *store, char *binary_hash)
22342234
#endif /* WASM_ENABLE_WASM_CACHE != 0 */
22352235

22362236
wasm_module_t *
2237-
wasm_module_new(wasm_store_t *store, const wasm_byte_vec_t *binary)
2237+
wasm_module_new_ex(wasm_store_t *store, const wasm_byte_vec_t *binary,
2238+
const LoadArgs *args)
22382239
{
22392240
char error_buf[128] = { 0 };
22402241
wasm_module_ex_t *module_ex = NULL;
@@ -2290,8 +2291,8 @@ wasm_module_new(wasm_store_t *store, const wasm_byte_vec_t *binary)
22902291
if (!module_ex->binary->data)
22912292
goto free_binary;
22922293

2293-
module_ex->module_comm_rt = wasm_runtime_load(
2294-
(uint8 *)module_ex->binary->data, (uint32)module_ex->binary->size,
2294+
module_ex->module_comm_rt = wasm_runtime_load_ex(
2295+
(uint8 *)module_ex->binary->data, (uint32)module_ex->binary->size, args,
22952296
error_buf, (uint32)sizeof(error_buf));
22962297
if (!(module_ex->module_comm_rt)) {
22972298
LOG_ERROR("%s", error_buf);
@@ -2337,6 +2338,14 @@ wasm_module_new(wasm_store_t *store, const wasm_byte_vec_t *binary)
23372338
return NULL;
23382339
}
23392340

2341+
wasm_module_t *
2342+
wasm_module_new(wasm_store_t *store, const wasm_byte_vec_t *binary)
2343+
{
2344+
LoadArgs args = { 0 };
2345+
args.name = "";
2346+
return wasm_module_new_ex(store, binary, &args);
2347+
}
2348+
23402349
bool
23412350
wasm_module_validate(wasm_store_t *store, const wasm_byte_vec_t *binary)
23422351
{

0 commit comments

Comments
 (0)