Skip to content

Commit 3b8ef89

Browse files
authored
Clone data segments when specified with load args (#3463)
Follow-up on #3389, specifically: #3389 (comment) If we want to free the wasm binary buffer early, we need to clone the data segments into the module. That's because, in case of [passive data segments](https://webassembly.github.io/threads/core/syntax/modules.html#syntax-data), they can be referred during wasm execution.
1 parent f378edc commit 3b8ef89

9 files changed

Lines changed: 81 additions & 60 deletions

File tree

core/iwasm/common/wasm_c_api.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3007,13 +3007,12 @@ wasm_module_get_name(wasm_module_t *module)
30073007
}
30083008

30093009
bool
3010-
wasm_module_is_underlying_binary_freeable(
3011-
const wasm_module_t *module, const struct wasm_instance_t *instance)
3010+
wasm_module_is_underlying_binary_freeable(const wasm_module_t *module)
30123011
{
30133012
if (((wasm_module_ex_t *)module)->is_binary_cloned)
30143013
return true;
30153014

3016-
return wasm_runtime_is_underlying_binary_freeable(instance->inst_comm_rt);
3015+
return wasm_runtime_is_underlying_binary_freeable(*module);
30173016
}
30183017

30193018
static wasm_func_t *

core/iwasm/common/wasm_runtime_common.c

Lines changed: 7 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7322,49 +7322,36 @@ wasm_runtime_detect_native_stack_overflow_size(WASMExecEnv *exec_env,
73227322
}
73237323

73247324
WASM_RUNTIME_API_EXTERN bool
7325-
wasm_runtime_is_underlying_binary_freeable(const wasm_module_inst_t module_inst)
7325+
wasm_runtime_is_underlying_binary_freeable(WASMModuleCommon *const module)
73267326
{
7327-
uint32 i;
7328-
73297327
#if WASM_ENABLE_INTERP != 0
7330-
if (module_inst->module_type == Wasm_Module_Bytecode) {
7328+
if (module->module_type == Wasm_Module_Bytecode) {
73317329
#if (WASM_ENABLE_JIT != 0 || WASM_ENABLE_FAST_JIT != 0) \
73327330
&& (WASM_ENABLE_LAZY_JIT != 0)
73337331
return false;
73347332
#elif WASM_ENABLE_FAST_INTERP == 0
73357333
return false;
73367334
#else
73377335
/* Fast interpreter mode */
7338-
WASMModule *module = ((WASMModuleInstance *)module_inst)->module;
7339-
if (!module->is_binary_freeable)
7336+
if (!((WASMModule *)module)->is_binary_freeable)
73407337
return false;
73417338
#if WASM_ENABLE_GC != 0 && WASM_ENABLE_STRINGREF != 0
7342-
if (module->string_literal_ptrs)
7339+
if (((WASMModule *)module)->string_literal_ptrs)
73437340
return false;
73447341
#endif
7345-
#if WASM_ENABLE_BULK_MEMORY != 0
7346-
for (i = 0; i < module->data_seg_count; i++)
7347-
if (!bh_bitmap_get_bit(
7348-
((WASMModuleInstance *)module_inst)->e->common.data_dropped,
7349-
i))
7350-
return false;
7351-
#endif
73527342
#endif
73537343
}
73547344
#endif /* WASM_ENABLE_INTERP != 0 */
73557345
#if WASM_ENABLE_AOT != 0
7356-
if (module_inst->module_type == Wasm_Module_AoT) {
7357-
AOTModule *module =
7358-
(AOTModule *)((AOTModuleInstance *)module_inst)->module;
7359-
if (!module->is_binary_freeable)
7346+
if (module->module_type == Wasm_Module_AoT) {
7347+
if (!((AOTModule *)module)->is_binary_freeable)
73607348
return false;
73617349
#if WASM_ENABLE_GC != 0 && WASM_ENABLE_STRINGREF != 0
7362-
if (module->string_literal_ptrs)
7350+
if (((AOTModule *)module)->string_literal_ptrs)
73637351
return false;
73647352
#endif
73657353
}
73667354
#endif /* WASM_ENABLE_AOT != 0 */
73677355

7368-
(void)i;
73697356
return true;
73707357
}

core/iwasm/common/wasm_runtime_common.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1200,8 +1200,7 @@ wasm_runtime_detect_native_stack_overflow_size(WASMExecEnv *exec_env,
12001200
uint32 requested_size);
12011201

12021202
WASM_RUNTIME_API_EXTERN bool
1203-
wasm_runtime_is_underlying_binary_freeable(
1204-
const wasm_module_inst_t module_inst);
1203+
wasm_runtime_is_underlying_binary_freeable(WASMModuleCommon *const module);
12051204

12061205
#if WASM_ENABLE_LINUX_PERF != 0
12071206
bool

core/iwasm/include/wasm_c_api.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -563,7 +563,7 @@ WASM_API_EXTERN void wasm_shared_module_delete(own wasm_shared_module_t*);
563563
WASM_API_EXTERN bool wasm_module_set_name(wasm_module_t*, const char* name);
564564
WASM_API_EXTERN const char *wasm_module_get_name(wasm_module_t*);
565565

566-
WASM_API_EXTERN bool wasm_module_is_underlying_binary_freeable(const wasm_module_t *module, const struct wasm_instance_t* instance);
566+
WASM_API_EXTERN bool wasm_module_is_underlying_binary_freeable(const wasm_module_t *module);
567567

568568

569569
// Function Instances

core/iwasm/include/wasm_export.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1918,12 +1918,11 @@ wasm_runtime_detect_native_stack_overflow_size(wasm_exec_env_t exec_env,
19181918
/**
19191919
* Query whether the wasm binary buffer used to create the module can be freed
19201920
*
1921-
* @param module_inst the target module instance
1921+
* @param module the target module
19221922
* @return true if the wasm binary buffer can be freed
19231923
*/
19241924
WASM_RUNTIME_API_EXTERN bool
1925-
wasm_runtime_is_underlying_binary_freeable(
1926-
const wasm_module_inst_t module_inst);
1925+
wasm_runtime_is_underlying_binary_freeable(const wasm_module_t module);
19271926

19281927
#ifdef __cplusplus
19291928
}

core/iwasm/interpreter/wasm.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -752,6 +752,7 @@ typedef struct WASMDataSeg {
752752
bool is_passive;
753753
#endif
754754
uint8 *data;
755+
bool is_data_cloned;
755756
} WASMDataSeg;
756757

757758
typedef struct BlockAddr {

core/iwasm/interpreter/wasm_loader.c

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4705,8 +4705,8 @@ load_table_segment_section(const uint8 *buf, const uint8 *buf_end,
47054705

47064706
static bool
47074707
load_data_segment_section(const uint8 *buf, const uint8 *buf_end,
4708-
WASMModule *module, char *error_buf,
4709-
uint32 error_buf_size)
4708+
WASMModule *module, bool clone_data_seg,
4709+
char *error_buf, uint32 error_buf_size)
47104710
{
47114711
const uint8 *p = buf, *p_end = buf_end;
47124712
uint32 data_seg_count, i, mem_index, data_seg_len;
@@ -4836,7 +4836,19 @@ load_data_segment_section(const uint8 *buf, const uint8 *buf_end,
48364836

48374837
dataseg->data_length = data_seg_len;
48384838
CHECK_BUF(p, p_end, data_seg_len);
4839-
dataseg->data = (uint8 *)p;
4839+
if (clone_data_seg) {
4840+
if (!(dataseg->data = loader_malloc(
4841+
dataseg->data_length, error_buf, error_buf_size))) {
4842+
return false;
4843+
}
4844+
4845+
bh_memcpy_s(dataseg->data, dataseg->data_length, p,
4846+
data_seg_len);
4847+
}
4848+
else {
4849+
dataseg->data = (uint8 *)p;
4850+
}
4851+
dataseg->is_data_cloned = clone_data_seg;
48404852
p += data_seg_len;
48414853
}
48424854
}
@@ -5748,8 +5760,8 @@ static void **handle_table;
57485760

57495761
static bool
57505762
load_from_sections(WASMModule *module, WASMSection *sections,
5751-
bool is_load_from_file_buf, char *error_buf,
5752-
uint32 error_buf_size)
5763+
bool is_load_from_file_buf, bool wasm_binary_freeable,
5764+
char *error_buf, uint32 error_buf_size)
57535765
{
57545766
WASMExport *export;
57555767
WASMSection *section = sections;
@@ -5764,6 +5776,8 @@ load_from_sections(WASMModule *module, WASMSection *sections,
57645776
uint32 aux_heap_base_global_index = (uint32)-1;
57655777
WASMFuncType *func_type;
57665778
uint8 malloc_free_io_type = VALUE_TYPE_I32;
5779+
bool reuse_const_strings = is_load_from_file_buf && !wasm_binary_freeable;
5780+
bool clone_data_seg = is_load_from_file_buf && wasm_binary_freeable;
57675781

57685782
/* Find code and function sections if have */
57695783
while (section) {
@@ -5790,7 +5804,7 @@ load_from_sections(WASMModule *module, WASMSection *sections,
57905804
case SECTION_TYPE_USER:
57915805
/* unsupported user section, ignore it. */
57925806
if (!load_user_section(buf, buf_end, module,
5793-
is_load_from_file_buf, error_buf,
5807+
reuse_const_strings, error_buf,
57945808
error_buf_size))
57955809
return false;
57965810
break;
@@ -5801,7 +5815,7 @@ load_from_sections(WASMModule *module, WASMSection *sections,
58015815
break;
58025816
case SECTION_TYPE_IMPORT:
58035817
if (!load_import_section(buf, buf_end, module,
5804-
is_load_from_file_buf, error_buf,
5818+
reuse_const_strings, error_buf,
58055819
error_buf_size))
58065820
return false;
58075821
break;
@@ -5835,7 +5849,7 @@ load_from_sections(WASMModule *module, WASMSection *sections,
58355849
break;
58365850
case SECTION_TYPE_EXPORT:
58375851
if (!load_export_section(buf, buf_end, module,
5838-
is_load_from_file_buf, error_buf,
5852+
reuse_const_strings, error_buf,
58395853
error_buf_size))
58405854
return false;
58415855
break;
@@ -5855,7 +5869,8 @@ load_from_sections(WASMModule *module, WASMSection *sections,
58555869
return false;
58565870
break;
58575871
case SECTION_TYPE_DATA:
5858-
if (!load_data_segment_section(buf, buf_end, module, error_buf,
5872+
if (!load_data_segment_section(buf, buf_end, module,
5873+
clone_data_seg, error_buf,
58595874
error_buf_size))
58605875
return false;
58615876
break;
@@ -5869,7 +5884,7 @@ load_from_sections(WASMModule *module, WASMSection *sections,
58695884
#if WASM_ENABLE_STRINGREF != 0
58705885
case SECTION_TYPE_STRINGREF:
58715886
if (!load_stringref_section(buf, buf_end, module,
5872-
is_load_from_file_buf, error_buf,
5887+
reuse_const_strings, error_buf,
58735888
error_buf_size))
58745889
return false;
58755890
break;
@@ -6321,7 +6336,7 @@ wasm_loader_load_from_sections(WASMSection *section_list, char *error_buf,
63216336
if (!module)
63226337
return NULL;
63236338

6324-
if (!load_from_sections(module, section_list, false, error_buf,
6339+
if (!load_from_sections(module, section_list, false, true, error_buf,
63256340
error_buf_size)) {
63266341
wasm_loader_unload(module);
63276342
return NULL;
@@ -6494,7 +6509,7 @@ load(const uint8 *buf, uint32 size, WASMModule *module,
64946509
}
64956510

64966511
if (!create_sections(buf, size, &section_list, error_buf, error_buf_size)
6497-
|| !load_from_sections(module, section_list, !wasm_binary_freeable,
6512+
|| !load_from_sections(module, section_list, true, wasm_binary_freeable,
64986513
error_buf, error_buf_size)) {
64996514
destroy_sections(section_list);
65006515
return false;
@@ -6823,8 +6838,11 @@ wasm_loader_unload(WASMModule *module)
68236838

68246839
if (module->data_segments) {
68256840
for (i = 0; i < module->data_seg_count; i++) {
6826-
if (module->data_segments[i])
6841+
if (module->data_segments[i]) {
6842+
if (module->data_segments[i]->is_data_cloned)
6843+
wasm_runtime_free(module->data_segments[i]->data);
68276844
wasm_runtime_free(module->data_segments[i]);
6845+
}
68286846
}
68296847
wasm_runtime_free(module->data_segments);
68306848
}

core/iwasm/interpreter/wasm_mini_loader.c

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1740,8 +1740,8 @@ load_table_segment_section(const uint8 *buf, const uint8 *buf_end,
17401740

17411741
static bool
17421742
load_data_segment_section(const uint8 *buf, const uint8 *buf_end,
1743-
WASMModule *module, char *error_buf,
1744-
uint32 error_buf_size)
1743+
WASMModule *module, bool clone_data_seg,
1744+
char *error_buf, uint32 error_buf_size)
17451745
{
17461746
const uint8 *p = buf, *p_end = buf_end;
17471747
uint32 data_seg_count, i, mem_index, data_seg_len;
@@ -1851,7 +1851,19 @@ load_data_segment_section(const uint8 *buf, const uint8 *buf_end,
18511851

18521852
dataseg->data_length = data_seg_len;
18531853
CHECK_BUF(p, p_end, data_seg_len);
1854-
dataseg->data = (uint8 *)p;
1854+
if (clone_data_seg) {
1855+
if (!(dataseg->data = loader_malloc(
1856+
dataseg->data_length, error_buf, error_buf_size))) {
1857+
return false;
1858+
}
1859+
1860+
bh_memcpy_s(dataseg->data, dataseg->data_length, p,
1861+
data_seg_len);
1862+
}
1863+
else {
1864+
dataseg->data = (uint8 *)p;
1865+
}
1866+
dataseg->is_data_cloned = clone_data_seg;
18551867
p += data_seg_len;
18561868
}
18571869
}
@@ -2549,8 +2561,8 @@ static void **handle_table;
25492561

25502562
static bool
25512563
load_from_sections(WASMModule *module, WASMSection *sections,
2552-
bool is_load_from_file_buf, char *error_buf,
2553-
uint32 error_buf_size)
2564+
bool is_load_from_file_buf, bool wasm_binary_freeable,
2565+
char *error_buf, uint32 error_buf_size)
25542566
{
25552567
WASMExport *export;
25562568
WASMSection *section = sections;
@@ -2565,6 +2577,8 @@ load_from_sections(WASMModule *module, WASMSection *sections,
25652577
uint32 aux_heap_base_global_index = (uint32)-1;
25662578
WASMFuncType *func_type;
25672579
uint8 malloc_free_io_type = VALUE_TYPE_I32;
2580+
bool reuse_const_strings = is_load_from_file_buf && !wasm_binary_freeable;
2581+
bool clone_data_seg = is_load_from_file_buf && wasm_binary_freeable;
25682582

25692583
/* Find code and function sections if have */
25702584
while (section) {
@@ -2588,7 +2602,7 @@ load_from_sections(WASMModule *module, WASMSection *sections,
25882602
case SECTION_TYPE_USER:
25892603
/* unsupported user section, ignore it. */
25902604
if (!load_user_section(buf, buf_end, module,
2591-
is_load_from_file_buf, error_buf,
2605+
reuse_const_strings, error_buf,
25922606
error_buf_size))
25932607
return false;
25942608
break;
@@ -2599,7 +2613,7 @@ load_from_sections(WASMModule *module, WASMSection *sections,
25992613
break;
26002614
case SECTION_TYPE_IMPORT:
26012615
if (!load_import_section(buf, buf_end, module,
2602-
is_load_from_file_buf, error_buf,
2616+
reuse_const_strings, error_buf,
26032617
error_buf_size))
26042618
return false;
26052619
break;
@@ -2625,7 +2639,7 @@ load_from_sections(WASMModule *module, WASMSection *sections,
26252639
break;
26262640
case SECTION_TYPE_EXPORT:
26272641
if (!load_export_section(buf, buf_end, module,
2628-
is_load_from_file_buf, error_buf,
2642+
reuse_const_strings, error_buf,
26292643
error_buf_size))
26302644
return false;
26312645
break;
@@ -2645,7 +2659,8 @@ load_from_sections(WASMModule *module, WASMSection *sections,
26452659
return false;
26462660
break;
26472661
case SECTION_TYPE_DATA:
2648-
if (!load_data_segment_section(buf, buf_end, module, error_buf,
2662+
if (!load_data_segment_section(buf, buf_end, module,
2663+
clone_data_seg, error_buf,
26492664
error_buf_size))
26502665
return false;
26512666
break;
@@ -3038,7 +3053,7 @@ wasm_loader_load_from_sections(WASMSection *section_list, char *error_buf,
30383053
if (!module)
30393054
return NULL;
30403055

3041-
if (!load_from_sections(module, section_list, false, error_buf,
3056+
if (!load_from_sections(module, section_list, false, true, error_buf,
30423057
error_buf_size)) {
30433058
wasm_loader_unload(module);
30443059
return NULL;
@@ -3193,7 +3208,7 @@ load(const uint8 *buf, uint32 size, WASMModule *module,
31933208
}
31943209

31953210
if (!create_sections(buf, size, &section_list, error_buf, error_buf_size)
3196-
|| !load_from_sections(module, section_list, !wasm_binary_freeable,
3211+
|| !load_from_sections(module, section_list, true, wasm_binary_freeable,
31973212
error_buf, error_buf_size)) {
31983213
destroy_sections(section_list);
31993214
return false;
@@ -3332,8 +3347,11 @@ wasm_loader_unload(WASMModule *module)
33323347

33333348
if (module->data_segments) {
33343349
for (i = 0; i < module->data_seg_count; i++) {
3335-
if (module->data_segments[i])
3350+
if (module->data_segments[i]) {
3351+
if (module->data_segments[i]->is_data_cloned)
3352+
wasm_runtime_free(module->data_segments[i]->data);
33363353
wasm_runtime_free(module->data_segments[i]);
3354+
}
33373355
}
33383356
wasm_runtime_free(module->data_segments);
33393357
}

samples/basic/src/free_buffer_early.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -89,19 +89,19 @@ main(int argc, char *argv_main[])
8989
goto fail;
9090
}
9191

92+
if (wasm_runtime_is_underlying_binary_freeable(module)) {
93+
printf("Able to free wasm binary buffer.\n");
94+
wasm_runtime_free(buffer);
95+
buffer = NULL;
96+
}
97+
9298
module_inst = wasm_runtime_instantiate(module, stack_size, heap_size,
9399
error_buf, sizeof(error_buf));
94100
if (!module_inst) {
95101
printf("Instantiate wasm module failed. error: %s.\n", error_buf);
96102
goto fail;
97103
}
98104

99-
if (wasm_runtime_is_underlying_binary_freeable(module_inst)) {
100-
printf("Able to free wasm binary buffer.\n");
101-
wasm_runtime_free(buffer);
102-
buffer = NULL;
103-
}
104-
105105
char *args[1] = { "3" };
106106
success = wasm_application_execute_func(module_inst, "mul7", 1, args);
107107
if (!success) {

0 commit comments

Comments
 (0)