From 180ee4c78af0e861f39f653102606bfa1a881c11 Mon Sep 17 00:00:00 2001 From: wenyongh Date: Sun, 8 Mar 2020 21:18:18 +0800 Subject: [PATCH] Add realloc func argument for memory allocator (#191) --- core/iwasm/aot/aot_runtime.c | 21 ++++++--- core/iwasm/common/wasm_runtime_common.c | 9 +++- core/iwasm/common/wasm_runtime_common.h | 1 + core/iwasm/include/wasm_export.h | 1 + core/iwasm/interpreter/wasm_runtime.c | 49 +++++++++---------- core/shared/include/bh_memory.h | 12 +++++ core/shared/include/mem_alloc.h | 3 ++ core/shared/mem-alloc/bh_memory.c | 54 ++++++++++++++++++++- core/shared/mem-alloc/ems/ems_alloc.c | 62 ++++++++++++++++++++++++- core/shared/mem-alloc/ems/ems_gc.h | 12 ++++- core/shared/mem-alloc/mem_alloc.c | 26 ++++++++++- product-mini/platforms/linux/main.c | 5 +- 12 files changed, 213 insertions(+), 42 deletions(-) diff --git a/core/iwasm/aot/aot_runtime.c b/core/iwasm/aot/aot_runtime.c index 44c7d48f..8c3ab5e1 100644 --- a/core/iwasm/aot/aot_runtime.c +++ b/core/iwasm/aot/aot_runtime.c @@ -750,8 +750,8 @@ aot_enlarge_memory(AOTModuleInstance *module_inst, uint32 inc_page_count) uint32 cur_page_count = module_inst->mem_cur_page_count; uint32 max_page_count = module_inst->mem_max_page_count; uint32 total_page_count = cur_page_count + inc_page_count; - uint32 old_size = num_bytes_per_page * cur_page_count; uint64 total_size = (uint64)num_bytes_per_page * total_page_count; + uint32 total_size_old; if (inc_page_count <= 0) /* No need to enlarge memory */ @@ -763,20 +763,29 @@ aot_enlarge_memory(AOTModuleInstance *module_inst, uint32 inc_page_count) return false; } - if (total_size >= UINT32_MAX - || !(mem_data_new = wasm_malloc((uint32)total_size))) { + if (total_size >= UINT32_MAX) { aot_set_exception(module_inst, "fail to enlarge memory."); return false; } - memcpy(mem_data_new, mem_data_old, old_size); - memset(mem_data_new + old_size, 0, (uint32)total_size - old_size); + if (!(mem_data_new = wasm_realloc(mem_data_old, (uint32)total_size))) { + if (!(mem_data_new = wasm_malloc((uint32)total_size))) { + aot_set_exception(module_inst, "fail to enlarge memory."); + return false; + } + total_size_old = module_inst->memory_data_size; + bh_memcpy_s(mem_data_new, (uint32)total_size, + mem_data_old, total_size_old); + memset(mem_data_new + total_size_old, + 0, (uint32)total_size - total_size_old); + wasm_free(mem_data_old); + } + module_inst->mem_cur_page_count = total_page_count; module_inst->memory_data_size = (uint32)total_size; module_inst->memory_data.ptr = mem_data_new; module_inst->memory_data_end.ptr = mem_data_new + (uint32)total_size; - wasm_free(mem_data_old); return true; } diff --git a/core/iwasm/common/wasm_runtime_common.c b/core/iwasm/common/wasm_runtime_common.c index bdee993f..b97eed82 100644 --- a/core/iwasm/common/wasm_runtime_common.c +++ b/core/iwasm/common/wasm_runtime_common.c @@ -50,6 +50,10 @@ wasm_runtime_destroy() vm_thread_sys_destroy(); } +int bh_memory_init_with_allocator_internal(void *_malloc_func, + void *_realloc_func, + void *_free_func); + bool wasm_runtime_full_init(RuntimeInitArgs *init_args) { @@ -61,8 +65,11 @@ wasm_runtime_full_init(RuntimeInitArgs *init_args) } else if (init_args->mem_alloc_type == Alloc_With_Allocator) { void *malloc_func = init_args->mem_alloc.allocator.malloc_func; + void *realloc_func = init_args->mem_alloc.allocator.realloc_func; void *free_func = init_args->mem_alloc.allocator.free_func; - if (bh_memory_init_with_allocator(malloc_func, free_func) != 0) + if (bh_memory_init_with_allocator_internal(malloc_func, + realloc_func, + free_func) != 0) return false; } else diff --git a/core/iwasm/common/wasm_runtime_common.h b/core/iwasm/common/wasm_runtime_common.h index 28b279c4..0e92652a 100644 --- a/core/iwasm/common/wasm_runtime_common.h +++ b/core/iwasm/common/wasm_runtime_common.h @@ -23,6 +23,7 @@ extern "C" { #endif #define wasm_malloc bh_malloc +#define wasm_realloc bh_realloc #define wasm_free bh_free typedef struct WASMModuleCommon { diff --git a/core/iwasm/include/wasm_export.h b/core/iwasm/include/wasm_export.h index 635da7ff..c391a5ae 100644 --- a/core/iwasm/include/wasm_export.h +++ b/core/iwasm/include/wasm_export.h @@ -67,6 +67,7 @@ typedef struct RuntimeInitArgs { } pool; struct { void *malloc_func; + void *realloc_func; void *free_func; } allocator; } mem_alloc; diff --git a/core/iwasm/interpreter/wasm_runtime.c b/core/iwasm/interpreter/wasm_runtime.c index 5b97f15d..ea347517 100644 --- a/core/iwasm/interpreter/wasm_runtime.c +++ b/core/iwasm/interpreter/wasm_runtime.c @@ -1105,12 +1105,13 @@ bool wasm_enlarge_memory(WASMModuleInstance *module, uint32 inc_page_count) { #if WASM_ENABLE_MEMORY_GROW != 0 - WASMMemoryInstance *memory = module->default_memory; - WASMMemoryInstance *new_memory; + WASMMemoryInstance *memory = module->default_memory, *new_memory; + uint32 old_page_count = memory->cur_page_count, total_size_old; uint32 total_page_count = inc_page_count + memory->cur_page_count; uint64 total_size = offsetof(WASMMemoryInstance, base_addr) + memory->num_bytes_per_page * (uint64)total_page_count + memory->global_data_size; + uint8 *global_data_old; if (inc_page_count <= 0) /* No need to enlarge memory */ @@ -1122,43 +1123,39 @@ wasm_enlarge_memory(WASMModuleInstance *module, uint32 inc_page_count) return false; } - if (total_size >= UINT32_MAX - || !(new_memory = wasm_malloc((uint32)total_size))) { + if (total_size >= UINT32_MAX) { wasm_set_exception(module, "fail to enlarge memory."); return false; } - new_memory->num_bytes_per_page = memory->num_bytes_per_page; + if (!(new_memory = wasm_realloc(memory, (uint32)total_size))) { + if (!(new_memory = wasm_malloc((uint32)total_size))) { + wasm_set_exception(module, "fail to enlarge memory."); + return false; + } + total_size_old = memory->end_addr - (uint8*)memory; + bh_memcpy_s((uint8*)new_memory, (uint32)total_size, + (uint8*)memory, total_size_old); + memset((uint8*)new_memory + total_size_old, + 0, (uint32)total_size - total_size_old); + wasm_free(memory); + } + new_memory->cur_page_count = total_page_count; - new_memory->max_page_count = memory->max_page_count; - new_memory->memory_data = new_memory->base_addr; - new_memory->global_data = new_memory->memory_data + - memory->num_bytes_per_page * total_page_count; - new_memory->global_data_size = memory->global_data_size; + new_memory->num_bytes_per_page * total_page_count; + new_memory->end_addr = new_memory->global_data + new_memory->global_data_size; - new_memory->end_addr = new_memory->global_data + memory->global_data_size; + global_data_old = new_memory->memory_data + + new_memory->num_bytes_per_page * old_page_count; - /* Copy memory data */ - bh_memcpy_s(new_memory->memory_data, - (uint32)(memory->global_data - memory->memory_data), - memory->memory_data, - (uint32)(memory->global_data - memory->memory_data)); /* Copy global data */ bh_memcpy_s(new_memory->global_data, new_memory->global_data_size, - memory->global_data, memory->global_data_size); - /* Init free space of new memory */ - memset(new_memory->memory_data + memory->num_bytes_per_page * memory->cur_page_count, - 0, memory->num_bytes_per_page * (total_page_count - memory->cur_page_count)); - - new_memory->heap_data = memory->heap_data; - new_memory->heap_data_end = memory->heap_data_end; - new_memory->heap_handle = memory->heap_handle; - new_memory->heap_base_offset = memory->heap_base_offset; + global_data_old, new_memory->global_data_size); + memset(global_data_old, 0, new_memory->global_data_size); module->memories[0] = module->default_memory = new_memory; - wasm_free(memory); return true; #else /* else of WASM_ENABLE_MEMORY_GROW */ wasm_set_exception(module, "unsupported operation: enlarge memory."); diff --git a/core/shared/include/bh_memory.h b/core/shared/include/bh_memory.h index 4b3aa86d..182e0db2 100644 --- a/core/shared/include/bh_memory.h +++ b/core/shared/include/bh_memory.h @@ -58,6 +58,16 @@ unsigned bh_memory_pool_size(); */ void* bh_malloc(unsigned int size); +/** + * This function reallocates a memory chunk from system + * + * @param ptr the original memory + * @param size bytes need allocate + * + * @return the pointer to memory allocated + */ +void* bh_realloc(void *ptr, unsigned int size); + /** * This function frees memory chunk * @@ -68,9 +78,11 @@ void bh_free(void *ptr); #else void* bh_malloc_profile(const char *file, int line, const char *func, unsigned int size); +void* bh_realloc_profile(const char *file, int line, const char *func, void *ptr, unsigned int size); void bh_free_profile(const char *file, int line, const char *func, void *ptr); #define bh_malloc(size) bh_malloc_profile(__FILE__, __LINE__, __func__, size) +#define bh_realloc(ptr, size) bh_malloc_profile(__FILE__, __LINE__, __func__, ptr, size) #define bh_free(ptr) bh_free_profile(__FILE__, __LINE__, __func__, ptr) /** diff --git a/core/shared/include/mem_alloc.h b/core/shared/include/mem_alloc.h index 3e1cf957..9553de1a 100644 --- a/core/shared/include/mem_alloc.h +++ b/core/shared/include/mem_alloc.h @@ -23,6 +23,9 @@ mem_allocator_destroy(mem_allocator_t allocator); void * mem_allocator_malloc(mem_allocator_t allocator, uint32_t size); +void * +mem_allocator_realloc(mem_allocator_t allocator, void *ptr, uint32_t size); + void mem_allocator_free(mem_allocator_t allocator, void *ptr); diff --git a/core/shared/mem-alloc/bh_memory.c b/core/shared/mem-alloc/bh_memory.c index 236bf4fa..4de2b295 100644 --- a/core/shared/mem-alloc/bh_memory.c +++ b/core/shared/mem-alloc/bh_memory.c @@ -48,6 +48,7 @@ static Memory_Mode memory_mode = MEMORY_MODE_UNKNOWN; static mem_allocator_t pool_allocator = NULL; static void *(*malloc_func)(unsigned int size) = NULL; +static void *(*realloc_func)(void *ptr, unsigned int size) = NULL; static void (*free_func)(void *ptr) = NULL; static unsigned int global_pool_size; @@ -69,11 +70,14 @@ int bh_memory_init_with_pool(void *mem, unsigned int bytes) return -1; } -int bh_memory_init_with_allocator(void *_malloc_func, void *_free_func) +int bh_memory_init_with_allocator_internal(void *_malloc_func, + void *_realloc_func, + void *_free_func) { if (_malloc_func && _free_func && _malloc_func != _free_func) { memory_mode = MEMORY_MODE_ALLOCATOR; malloc_func = _malloc_func; + realloc_func = _realloc_func; free_func = _free_func; #if BEIHAI_ENABLE_MEMORY_PROFILING != 0 vm_mutex_init(&profile_lock); @@ -85,6 +89,12 @@ int bh_memory_init_with_allocator(void *_malloc_func, void *_free_func) return -1; } +int bh_memory_init_with_allocator(void *_malloc_func, void *_free_func) +{ + return bh_memory_init_with_allocator_internal(_malloc_func, + NULL, _free_func); +} + void bh_memory_destroy() { #if BEIHAI_ENABLE_MEMORY_PROFILING != 0 @@ -115,6 +125,21 @@ void* bh_malloc_internal(unsigned int size) } } +void* bh_realloc_internal(void *ptr, unsigned int size) +{ + if (memory_mode == MEMORY_MODE_UNKNOWN) { + bh_printf("bh_realloc failed: memory hasn't been initialize.\n"); + return NULL; + } else if (memory_mode == MEMORY_MODE_POOL) { + return mem_allocator_realloc(pool_allocator, ptr, size); + } else { + if (realloc_func) + return realloc_func(ptr, size); + else + return NULL; + } +} + void bh_free_internal(void *ptr) { if (memory_mode == MEMORY_MODE_UNKNOWN) { @@ -267,6 +292,11 @@ void* bh_malloc(unsigned int size) return bh_malloc_internal(size); } +void* bh_realloc(void *ptr, unsigned int size) +{ + return bh_realloc_internal(ptr, size); +} + void bh_free(void *ptr) { bh_free_internal(ptr); @@ -282,6 +312,11 @@ void* bh_malloc(unsigned int size) return malloc(size); } +void* bh_realloc(void *ptr, unsigned int size) +{ + return realloc(ptr, size); +} + void bh_free(void *ptr) { if (ptr) @@ -306,6 +341,23 @@ void* bh_malloc_profile(const char *file, return malloc(size); } +void* bh_realloc_profile(const char *file, + int line, + const char *func, + void *ptr, + unsigned int size) +{ + (void)file; + (void)line; + (void)func; + + (void)memory_profiles_list; + (void)profile_lock; + (void)memory_in_use; + + return realloc(ptr, size); +} + void bh_free_profile(const char *file, int line, const char *func, void *ptr) { (void)file; diff --git a/core/shared/mem-alloc/ems/ems_alloc.c b/core/shared/mem-alloc/ems/ems_alloc.c index 19e76ade..3bd2e9ae 100644 --- a/core/shared/mem-alloc/ems/ems_alloc.c +++ b/core/shared/mem-alloc/ems/ems_alloc.c @@ -348,7 +348,7 @@ unsigned long g_total_malloc = 0; unsigned long g_total_free = 0; gc_object_t _gc_alloc_vo_i_heap(void *vheap, - gc_size_t size ALLOC_EXTRA_PARAMETERS) + gc_size_t size ALLOC_EXTRA_PARAMETERS) { gc_heap_t* heap = (gc_heap_t*) vheap; hmu_t *hmu = NULL; @@ -381,12 +381,70 @@ gc_object_t _gc_alloc_vo_i_heap(void *vheap, bh_printf("HEAP.ALLOC: heap: %p, size: %u", heap, size); #endif - FINISH: +FINISH: gct_vm_mutex_unlock(&heap->lock); return ret; } +gc_object_t _gc_realloc_vo_i_heap(void *vheap, void *ptr, + gc_size_t size ALLOC_EXTRA_PARAMETERS) +{ + gc_heap_t* heap = (gc_heap_t*) vheap; + hmu_t *hmu = NULL, *hmu_old = NULL; + gc_object_t ret = (gc_object_t) NULL, obj_old = (gc_object_t)ptr; + gc_size_t tot_size = 0, size_old = 0; + + if (obj_old) { + hmu_old = obj_to_hmu(obj_old); + size_old = hmu_get_size(hmu_old); + size_old -= HMU_SIZE + OBJ_PREFIX_SIZE + OBJ_SUFFIX_SIZE; + if (size < size_old) + return NULL; + if (size == size_old) + return obj_old; + } + + /* align size*/ + tot_size = GC_ALIGN_8(size + HMU_SIZE + OBJ_PREFIX_SIZE + OBJ_SUFFIX_SIZE); /* hmu header, prefix, suffix*/ + if (tot_size < size) + return NULL; + + gct_vm_mutex_lock(&heap->lock); + + hmu = alloc_hmu_ex(heap, tot_size); + if (!hmu) + goto FINISH; + + g_total_malloc += tot_size; + + hmu_set_ut(hmu, HMU_VO); + hmu_unfree_vo(hmu); + +#if defined(GC_VERIFY) + hmu_init_prefix_and_suffix(hmu, tot_size, file_name, line_number); +#endif + + ret = hmu_to_obj(hmu); + +#if BH_ENABLE_MEMORY_PROFILING != 0 + bh_printf("HEAP.ALLOC: heap: %p, size: %u", heap, size); +#endif + +FINISH: + gct_vm_mutex_unlock(&heap->lock); + + if (ret) { + memset(ret, 0, size); + if (obj_old) { + memcpy(ret, obj_old, size_old); + gc_free_h(vheap, obj_old); + } + } + + return ret; +} + /* see ems_gc.h for description*/ gc_object_t _gc_alloc_jo_i_heap(void *vheap, gc_size_t size ALLOC_EXTRA_PARAMETERS) diff --git a/core/shared/mem-alloc/ems/ems_gc.h b/core/shared/mem-alloc/ems/ems_gc.h index c24fb841..cac4a784 100644 --- a/core/shared/mem-alloc/ems/ems_gc.h +++ b/core/shared/mem-alloc/ems/ems_gc.h @@ -193,12 +193,14 @@ extern int gc_set_threshold_factor(void *heap, unsigned int factor); # define ALLOC_EXTRA_ARGUMENTS , __FILE__, __LINE__ # define ALLOC_PASSDOWN_EXTRA_ARGUMENTS , file_name, line_number # define gc_alloc_vo_h(heap, size) gc_alloc_vo_i_heap(heap, size, __FILE__, __LINE__) +# define gc_realloc_vo_h(heap, ptr, size) gc_realloc_vo_i_heap(heap, ptr, size, __FILE__, __LINE__) # define gc_free_h(heap, obj) gc_free_i_heap(heap, obj, __FILE__, __LINE__) #else # define ALLOC_EXTRA_PARAMETERS # define ALLOC_EXTRA_ARGUMENTS # define ALLOC_PASSDOWN_EXTRA_ARGUMENTS # define gc_alloc_vo_h gc_alloc_vo_i_heap +# define gc_realloc_vo_h gc_realloc_vo_i_heap # define gc_free_h gc_free_i_heap #endif @@ -221,16 +223,22 @@ extern int gci_gc_heap(void *heap); * NULL if failed. */ extern gc_object_t _gc_alloc_vo_i_heap(void *heap, - gc_size_t size ALLOC_EXTRA_PARAMETERS); + gc_size_t size ALLOC_EXTRA_PARAMETERS); +extern gc_object_t _gc_realloc_vo_i_heap(void *heap, void *ptr, + gc_size_t size ALLOC_EXTRA_PARAMETERS); extern gc_object_t _gc_alloc_jo_i_heap(void *heap, - gc_size_t size ALLOC_EXTRA_PARAMETERS); + gc_size_t size ALLOC_EXTRA_PARAMETERS); #ifdef INSTRUMENT_TEST_ENABLED extern gc_object_t gc_alloc_vo_i_heap_instr(void *heap, gc_size_t size, const char* func_name ); +extern gc_object_t gc_realloc_vo_i_heap_instr(void *heap, void *ptr, gc_size_t size, + const char* func_name ); extern gc_object_t gc_alloc_jo_i_heap_instr(void *heap, gc_size_t size, const char* func_name); # define gc_alloc_vo_i_heap(heap, size) gc_alloc_vo_i_heap_instr(heap, size, __FUNCTION__) +# define gc_realloc_vo_i_heap(heap, ptr, size) gc_realloc_vo_i_heap_instr(heap, ptr, size, __FUNCTION__) # define gc_alloc_jo_i_heap(heap, size) gc_alloc_jo_i_heap_instr(heap, size, __FUNCTION__) #else # define gc_alloc_vo_i_heap _gc_alloc_vo_i_heap +# define gc_realloc_vo_i_heap _gc_realloc_vo_i_heap # define gc_alloc_jo_i_heap _gc_alloc_jo_i_heap #endif diff --git a/core/shared/mem-alloc/mem_alloc.c b/core/shared/mem-alloc/mem_alloc.c index 72670ff5..71ae701b 100644 --- a/core/shared/mem-alloc/mem_alloc.c +++ b/core/shared/mem-alloc/mem_alloc.c @@ -26,6 +26,12 @@ mem_allocator_malloc(mem_allocator_t allocator, uint32_t size) return gc_alloc_vo_h((gc_handle_t) allocator, size); } +void * +mem_allocator_realloc(mem_allocator_t allocator, void *ptr, uint32_t size) +{ + return gc_realloc_vo_h((gc_handle_t) allocator, ptr, size); +} + void mem_allocator_free(mem_allocator_t allocator, void *ptr) { if (ptr) @@ -101,8 +107,8 @@ mem_allocator_malloc(mem_allocator_t allocator, uint32_t size) mem_allocator_tlsf *allocator_tlsf = (mem_allocator_tlsf *)allocator; if (size == 0) - /* tlsf doesn't allow to allocate 0 byte */ - size = 1; + /* tlsf doesn't allow to allocate 0 byte */ + size = 1; vm_mutex_lock(&allocator_tlsf->lock); ret = tlsf_malloc(allocator_tlsf->tlsf, size); @@ -110,6 +116,22 @@ mem_allocator_malloc(mem_allocator_t allocator, uint32_t size) return ret; } +void * +mem_allocator_realloc(mem_allocator_t allocator, void *ptr, uint32_t size) +{ + void *ret; + mem_allocator_tlsf *allocator_tlsf = (mem_allocator_tlsf *)allocator; + + if (size == 0) + /* tlsf doesn't allow to allocate 0 byte */ + size = 1; + + vm_mutex_lock(&allocator_tlsf->lock); + ret = tlsf_realloc(allocator_tlsf->tlsf, ptr, size); + vm_mutex_unlock(&allocator_tlsf->lock); + return ret; +} + void mem_allocator_free(mem_allocator_t allocator, void *ptr) { diff --git a/product-mini/platforms/linux/main.c b/product-mini/platforms/linux/main.c index 7bdf7a18..0cc3ca08 100644 --- a/product-mini/platforms/linux/main.c +++ b/product-mini/platforms/linux/main.c @@ -238,6 +238,7 @@ int main(int argc, char *argv[]) #else init_args.mem_alloc_type = Alloc_With_Allocator; init_args.mem_alloc.allocator.malloc_func = malloc; + init_args.mem_alloc.allocator.realloc_func = realloc; init_args.mem_alloc.allocator.free_func = free; #endif @@ -270,8 +271,8 @@ int main(int argc, char *argv[]) /* instantiate the module */ if (!(wasm_module_inst = wasm_runtime_instantiate(wasm_module, - 64 * 1024, /* stack size */ - 64 * 1024, /* heap size */ + 48 * 1024, /* stack size */ + 16 * 1024, /* heap size */ error_buf, sizeof(error_buf)))) { bh_printf("%s\n", error_buf);