Procházet zdrojové kódy

Make heap and linear memory contiguous to refine compilation time and footprint (#233)

Use FastISel for JIT mode
Use united aot version in aot file and aot runtime
Disable check signature failed warning for wamrc
Fix fast interpreter x86_32 float issue
Remove unused empty lvgl folder
wenyongh před 5 roky
rodič
revize
b40e79c160

+ 7 - 3
core/config.h

@@ -61,6 +61,9 @@ enum {
 #define WASM_ENABLE_AOT 0
 #endif
 
+#define AOT_MAGIC_NUMBER 0x746f6100
+#define AOT_CURRENT_VERSION 1
+
 #ifndef WASM_ENABLE_JIT
 #define WASM_ENABLE_JIT 0
 #endif
@@ -147,9 +150,6 @@ enum {
 /* Default watchdog interval in ms */
 #define DEFAULT_WATCHDOG_INTERVAL (3 * 60 * 1000)
 
-/* Support memory.grow opcode and enlargeMemory function */
-#define WASM_ENABLE_MEMORY_GROW 1
-
 /* The max percentage of global heap that app memory space can grow */
 #define APP_MEMORY_MAX_GLOBAL_HEAP_PERCENT 1 / 3
 
@@ -183,5 +183,9 @@ enum {
 #define BLOCK_ADDR_CACHE_SIZE 64
 #define BLOCK_ADDR_CONFLICT_SIZE 2
 
+#ifndef WASM_ENABLE_SPEC_TEST
+#define WASM_ENABLE_SPEC_TEST 0
+#endif
+
 #endif /* end of _CONFIG_H_ */
 

+ 159 - 147
core/iwasm/aot/aot_runtime.c

@@ -107,29 +107,64 @@ table_instantiate(AOTModuleInstance *module_inst, AOTModule *module,
 
 static bool
 memory_instantiate(AOTModuleInstance *module_inst, AOTModule *module,
-                   char *error_buf, uint32 error_buf_size)
+                   uint32 heap_size, char *error_buf, uint32 error_buf_size)
 {
     uint32 i, global_index, global_data_offset, base_offset, length;
     AOTMemInitData *data_seg;
-    uint64 total_size = (uint64)module->num_bytes_per_page * module->mem_init_page_count;
+    void *heap_handle;
+    uint64 memory_data_size = (uint64)module->num_bytes_per_page
+                              * module->mem_init_page_count;
+    uint64 total_size = heap_size + memory_data_size;
+    uint8 *p;
 
     /* Allocate memory */
     if (total_size >= UINT32_MAX
-        || !(module_inst->memory_data.ptr = wasm_runtime_malloc((uint32)total_size))) {
+        || !(p = wasm_runtime_malloc((uint32)total_size))) {
         set_error_buf(error_buf, error_buf_size,
                       "AOT module instantiate failed: allocate memory failed.");
         return false;
     }
 
-    memset(module_inst->memory_data.ptr, 0, (uint32)total_size);
+    memset(p, 0, (uint32)total_size);
+
+    /* Initialize heap info */
+    module_inst->heap_data.ptr = p;
+    p += heap_size;
+    module_inst->heap_data_end.ptr = p;
+    if (!(heap_handle = mem_allocator_create(module_inst->heap_data.ptr,
+                                             heap_size))) {
+        set_error_buf(error_buf, error_buf_size,
+                      "AOT module instantiate failed: init app heap failed.");
+        goto fail1;
+    }
+    module_inst->heap_handle.ptr = heap_handle;
+    module_inst->heap_data_size = heap_size;
+#if WASM_ENABLE_SPEC_TEST == 0
+    module_inst->heap_base_offset = -(int32)heap_size;
+#else
+    module_inst->heap_base_offset = 0;
+#endif
 
     /* Init memory info */
-    module_inst->memory_data_end.ptr = (uint8*)module_inst->memory_data.ptr
-                                       + total_size;
-    module_inst->memory_data_size = (uint32)total_size;
+    module_inst->memory_data.ptr = p;
+    p += (uint32)memory_data_size;
+    module_inst->memory_data_end.ptr = p;
+    module_inst->memory_data_size = (uint32)memory_data_size;
+#if WASM_ENABLE_SPEC_TEST == 0
+    module_inst->total_mem_size = (uint32)(heap_size + memory_data_size);
+#else
+    module_inst->total_mem_size = (uint32)memory_data_size;
+#endif
     module_inst->mem_cur_page_count = module->mem_init_page_count;
     module_inst->mem_max_page_count = module->mem_max_page_count;
 
+    if (module_inst->total_mem_size > 0) {
+        module_inst->mem_bound_check_1byte = module_inst->total_mem_size - 1;
+        module_inst->mem_bound_check_2bytes = module_inst->total_mem_size - 2;
+        module_inst->mem_bound_check_4bytes = module_inst->total_mem_size - 4;
+        module_inst->mem_bound_check_8bytes = module_inst->total_mem_size - 8;
+    }
+
     if (module->mem_init_page_count > 0) {
         for (i = 0; i < module->mem_init_data_count; i++) {
             data_seg = module->mem_init_data_list[i];
@@ -165,11 +200,9 @@ memory_instantiate(AOTModuleInstance *module_inst, AOTModule *module,
             if (length > 0
                 && (base_offset >= module_inst->memory_data_size
                     || base_offset + length > module_inst->memory_data_size)) {
-                wasm_runtime_free(module_inst->memory_data.ptr);
-                module_inst->memory_data.ptr = NULL;
                 set_error_buf(error_buf, error_buf_size,
                              "AOT module instantiate failed: data segment out of range.");
-                return false;
+                goto fail2;
             }
 
             /* Copy memory data */
@@ -179,6 +212,14 @@ memory_instantiate(AOTModuleInstance *module_inst, AOTModule *module,
     }
 
     return true;
+
+fail2:
+    mem_allocator_destroy(module_inst->heap_handle.ptr);
+    module_inst->heap_handle.ptr = NULL;
+fail1:
+    wasm_runtime_free(module_inst->heap_data.ptr);
+    module_inst->heap_data.ptr = NULL;
+    return false;
 }
 
 static bool
@@ -285,12 +326,11 @@ aot_instantiate(AOTModule *module,
 {
     AOTModuleInstance *module_inst;
     uint32 module_inst_struct_size =
-        offsetof(AOTModuleInstance, global_table_heap_data.bytes);
+        offsetof(AOTModuleInstance, global_table_data.bytes);
     uint64 table_data_size = (uint64)module->table_size * sizeof(uint32);
     uint64 total_size = (uint64)module_inst_struct_size
                         + module->global_data_size
-                        + table_data_size + heap_size;
-    void *heap_handle;
+                        + table_data_size;
     uint8 *p;
 
     /* Check heap size */
@@ -330,27 +370,9 @@ aot_instantiate(AOTModule *module,
     if (!table_instantiate(module_inst, module, error_buf, error_buf_size))
         goto fail;
 
-    /* Initialize heap info */
-    p += (uint32)table_data_size;
-    module_inst->heap_data.ptr = p;
-    p += heap_size;
-    module_inst->heap_data_end.ptr = p;
-    module_inst->heap_data_size = heap_size;
-#if WASM_ENABLE_MEMORY_GROW != 0
-    module_inst->heap_base_offset = DEFAULT_APP_HEAP_BASE_OFFSET;
-#else
-    module_inst->heap_base_offset = module_inst->memory_data_size;
-#endif
-    if (!(heap_handle = mem_allocator_create(module_inst->heap_data.ptr,
-                                             heap_size))) {
-        set_error_buf(error_buf, error_buf_size,
-                      "AOT module instantiate failed: init app heap failed.");
-        goto fail;
-    }
-    module_inst->heap_handle.ptr = heap_handle;
-
     /* Initialize memory space */
-    if (!memory_instantiate(module_inst, module, error_buf, error_buf_size))
+    if (!memory_instantiate(module_inst, module, heap_size,
+                            error_buf, error_buf_size))
         goto fail;
 
     /* Initialize function pointers */
@@ -378,6 +400,10 @@ aot_instantiate(AOTModule *module,
     /* Initialize the thread related data */
     if (stack_size == 0)
         stack_size = DEFAULT_WASM_STACK_SIZE;
+#if WASM_ENABLE_SPEC_TEST != 0
+    if (stack_size < 48 *1024)
+        stack_size = 48 * 1024;
+#endif
     module_inst->default_wasm_stack_size = stack_size;
 
     /* Execute __post_instantiate function and start function*/
@@ -406,12 +432,12 @@ aot_deinstantiate(AOTModuleInstance *module_inst)
     wasm_runtime_destroy_wasi((WASMModuleInstanceCommon*)module_inst);
 #endif
 
-    if (module_inst->memory_data.ptr)
-        wasm_runtime_free(module_inst->memory_data.ptr);
-
     if (module_inst->heap_handle.ptr)
         mem_allocator_destroy(module_inst->heap_handle.ptr);
 
+    if (module_inst->heap_data.ptr)
+        wasm_runtime_free(module_inst->heap_data.ptr);
+
     if (module_inst->func_ptrs.ptr)
         wasm_runtime_free(module_inst->func_ptrs.ptr);
 
@@ -554,27 +580,23 @@ int32
 aot_module_malloc(AOTModuleInstance *module_inst, uint32 size,
                   void **p_native_addr)
 {
-    uint8 *addr =
-        mem_allocator_malloc(module_inst->heap_handle.ptr, size);
-
-    if (p_native_addr)
-        *p_native_addr = addr;
+    uint8 *addr = mem_allocator_malloc(module_inst->heap_handle.ptr, size);
     if (!addr) {
         aot_set_exception(module_inst, "out of memory");
         return 0;
     }
-    return (int32)(module_inst->heap_base_offset
-                   + (addr - (uint8*)module_inst->heap_data.ptr));
+    if (p_native_addr)
+        *p_native_addr = addr;
+    return (int32)(addr - (uint8*)module_inst->memory_data.ptr);
 }
 
 void
 aot_module_free(AOTModuleInstance *module_inst, int32 ptr)
 {
     if (ptr) {
-        uint8 *addr = (uint8*)module_inst->heap_data.ptr
-                       + (ptr - module_inst->heap_base_offset);
+        uint8 *addr = (uint8*)module_inst->memory_data.ptr + ptr;
         if ((uint8*)module_inst->heap_data.ptr < addr
-            && addr < (uint8*)module_inst->heap_data_end.ptr)
+            && addr < (uint8*)module_inst->memory_data.ptr)
             mem_allocator_free(module_inst->heap_handle.ptr, addr);
     }
 }
@@ -598,34 +620,16 @@ bool
 aot_validate_app_addr(AOTModuleInstance *module_inst,
                       int32 app_offset, uint32 size)
 {
-    uint8 *addr;
-
     /* integer overflow check */
     if(app_offset + (int32)size < app_offset) {
         goto fail;
     }
 
-    if (0 <= app_offset
-        && app_offset < (int32)module_inst->memory_data_size) {
-        addr = (uint8*)module_inst->memory_data.ptr + app_offset;
-        if (!((uint8*)module_inst->memory_data.ptr <= addr
-              && addr + size <= (uint8*)module_inst->memory_data_end.ptr))
-            goto fail;
-        return true;
-    }
-    /* Currently heap_size is no more than 1G, and heap_base_offset is 1G,
-       heap_base_offset + heap_data_size will not be larger than INT32_MAX */
-    else if (module_inst->heap_base_offset < app_offset
-             && app_offset < module_inst->heap_base_offset
-                             + (int32)module_inst->heap_data_size) {
-        addr = (uint8*)module_inst->heap_data.ptr
-               + (app_offset - module_inst->heap_base_offset);
-        if (!((uint8*)module_inst->heap_data.ptr <= addr
-               && addr + size <= (uint8*)module_inst->heap_data_end.ptr))
-            goto fail;
-        return true;
+    if (app_offset <= module_inst->heap_base_offset
+        || app_offset + (int32)size > (int32)module_inst->memory_data_size) {
+        goto fail;
     }
-
+    return true;
 fail:
     aot_set_exception(module_inst, "out of bounds memory access");
     return false;
@@ -635,20 +639,20 @@ bool
 aot_validate_native_addr(AOTModuleInstance *module_inst,
                          void *native_ptr, uint32 size)
 {
-    uint8 *addr = native_ptr;
+    uint8 *addr = (uint8*)native_ptr;
+    int32 memory_data_size = (int32)module_inst->memory_data_size;
 
     /* integer overflow check */
     if (addr + size < addr) {
         goto fail;
     }
 
-    if (((uint8*)module_inst->memory_data.ptr <= addr
-         && addr + size <= (uint8*)module_inst->memory_data_end.ptr)
-        || ((uint8*)module_inst->heap_data.ptr <= addr
-            && addr + size <= (uint8*)module_inst->heap_data_end.ptr)
-       )
-        return true;
-
+    if (addr <= (uint8*)module_inst->heap_data.ptr
+        || addr + size > (uint8*)module_inst->memory_data.ptr
+                         + memory_data_size) {
+        goto fail;
+    }
+    return true;
 fail:
     aot_set_exception(module_inst, "out of bounds memory access");
     return false;
@@ -657,30 +661,24 @@ fail:
 void *
 aot_addr_app_to_native(AOTModuleInstance *module_inst, int32 app_offset)
 {
-    if (0 <= app_offset && app_offset < module_inst->heap_base_offset)
-        return (uint8*)module_inst->memory_data.ptr + app_offset;
+    int32 memory_data_size = (int32)module_inst->memory_data_size;
 
     if (module_inst->heap_base_offset < app_offset
-        && app_offset < module_inst->heap_base_offset
-                        + (int32)module_inst->heap_data_size)
-        return (uint8*)module_inst->heap_data.ptr
-               + (app_offset - module_inst->heap_base_offset);
-
+        && app_offset < memory_data_size)
+        return (uint8*)module_inst->memory_data.ptr + app_offset;
     return NULL;
 }
 
 int32
 aot_addr_native_to_app(AOTModuleInstance *module_inst, void *native_ptr)
 {
-    if ((uint8*)module_inst->memory_data.ptr <= (uint8*)native_ptr
-        && (uint8*)native_ptr < (uint8*)module_inst->memory_data_end.ptr)
-        return (int32)((uint8*)native_ptr - (uint8*)module_inst->memory_data.ptr);
-
-    if ((uint8*)module_inst->heap_data.ptr <= (uint8*)native_ptr
-        && (uint8*)native_ptr < (uint8*)module_inst->heap_data_end.ptr)
-        return (int32)(module_inst->heap_base_offset
-                       + ((uint8*)native_ptr - (uint8*)module_inst->heap_data.ptr));
+    uint8 *addr = (uint8*)native_ptr;
+    int32 memory_data_size = (int32)module_inst->memory_data_size;
 
+    if ((uint8*)module_inst->heap_data.ptr < addr
+        && addr < (uint8*)module_inst->memory_data.ptr
+                  + memory_data_size)
+        return (int32)(addr - (uint8*)module_inst->memory_data.ptr);
     return 0;
 }
 
@@ -690,27 +688,17 @@ aot_get_app_addr_range(AOTModuleInstance *module_inst,
                        int32 *p_app_start_offset,
                        int32 *p_app_end_offset)
 {
-    int32 app_start_offset, app_end_offset;
+    int32 memory_data_size = (int32)module_inst->memory_data_size;
 
-    if (0 <= app_offset && app_offset < (int32)module_inst->memory_data_size) {
-        app_start_offset = 0;
-        app_end_offset = (int32)module_inst->memory_data_size;
-    }
-    else if (module_inst->heap_base_offset < app_offset
-             && app_offset < module_inst->heap_base_offset
-                             + (int32)module_inst->heap_data_size) {
-        app_start_offset = module_inst->heap_base_offset;
-        app_end_offset = module_inst->heap_base_offset
-                         + (int32)module_inst->heap_data_size;
+    if (module_inst->heap_base_offset < app_offset
+        && app_offset < memory_data_size) {
+        if (p_app_start_offset)
+            *p_app_start_offset = module_inst->heap_base_offset;
+        if (p_app_end_offset)
+            *p_app_end_offset = memory_data_size;
+        return true;
     }
-    else
-        return false;
-
-    if (p_app_start_offset)
-        *p_app_start_offset = app_start_offset;
-    if (p_app_end_offset)
-        *p_app_end_offset = app_end_offset;
-    return true;
+    return false;
 }
 
 bool
@@ -719,39 +707,37 @@ aot_get_native_addr_range(AOTModuleInstance *module_inst,
                           uint8 **p_native_start_addr,
                           uint8 **p_native_end_addr)
 {
-    uint8 *native_start_addr, *native_end_addr;
-
-    if ((uint8*)module_inst->memory_data.ptr <= (uint8*)native_ptr
-        && (uint8*)native_ptr < (uint8*)module_inst->memory_data_end.ptr) {
-        native_start_addr = (uint8*)module_inst->memory_data.ptr;
-        native_end_addr = (uint8*)module_inst->memory_data_end.ptr;
-    }
-    else if ((uint8*)module_inst->heap_data.ptr <= (uint8*)native_ptr
-             && (uint8*)native_ptr < (uint8*)module_inst->heap_data_end.ptr) {
-        native_start_addr = (uint8*)module_inst->heap_data.ptr;
-        native_end_addr = (uint8*)module_inst->heap_data_end.ptr;
+    uint8 *addr = (uint8*)native_ptr;
+    int32 memory_data_size = (int32)module_inst->memory_data_size;
+
+    if ((uint8*)module_inst->heap_data.ptr < addr
+        && addr < (uint8*)module_inst->memory_data.ptr
+                  + memory_data_size) {
+        if (p_native_start_addr)
+            *p_native_start_addr = (uint8*)module_inst->heap_data.ptr;
+        if (p_native_end_addr)
+            *p_native_end_addr = (uint8*)module_inst->memory_data.ptr
+                                 + memory_data_size;
+        return true;
     }
-    else
-        return false;
-
-    if (p_native_start_addr)
-        *p_native_start_addr = native_start_addr;
-    if (p_native_end_addr)
-        *p_native_end_addr = native_end_addr;
-    return true;
+    return false;
 }
 
 bool
 aot_enlarge_memory(AOTModuleInstance *module_inst, uint32 inc_page_count)
 {
-    uint8 *mem_data_old = module_inst->memory_data.ptr, *mem_data_new;
+    uint8 *heap_data_old = module_inst->heap_data.ptr, *heap_data;
     uint32 num_bytes_per_page =
         ((AOTModule*)module_inst->aot_module.ptr)->num_bytes_per_page;
     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;
-    uint64 total_size = (uint64)num_bytes_per_page * total_page_count;
-    uint32 total_size_old = module_inst->memory_data_size;
+    uint64 memory_data_size = (uint64)num_bytes_per_page * total_page_count;
+    uint32 heap_size = (uint32)((uint8*)module_inst->memory_data.ptr
+                                - (uint8*)module_inst->heap_data.ptr);
+    uint32 total_size_old = heap_size + module_inst->memory_data_size;
+    uint64 total_size = heap_size + memory_data_size;
+    void *heap_handle_old = module_inst->heap_handle.ptr;
 
     if (inc_page_count <= 0)
         /* No need to enlarge memory */
@@ -768,24 +754,50 @@ aot_enlarge_memory(AOTModuleInstance *module_inst, uint32 inc_page_count)
         return false;
     }
 
-    if (!(mem_data_new = wasm_runtime_realloc(mem_data_old, (uint32)total_size))) {
-        if (!(mem_data_new = wasm_runtime_malloc((uint32)total_size))) {
+    /* Destroy heap's lock firstly, if its memory is re-allocated,
+       we cannot access its lock again. */
+    mem_allocator_destroy_lock(module_inst->heap_handle.ptr);
+    if (!(heap_data = wasm_runtime_realloc(heap_handle_old, (uint32)total_size))) {
+        if (!(heap_data = wasm_runtime_malloc((uint32)total_size))) {
+            /* Restore heap's lock if memory re-alloc failed */
+            mem_allocator_reinit_lock(module_inst->heap_handle.ptr);
             aot_set_exception(module_inst, "fail to enlarge memory.");
             return false;
         }
-        bh_memcpy_s(mem_data_new, (uint32)total_size,
-                    mem_data_old, total_size_old);
-        wasm_runtime_free(mem_data_old);
+        bh_memcpy_s(heap_data, (uint32)total_size,
+                    heap_data_old, total_size_old);
+        wasm_runtime_free(heap_data_old);
     }
 
-    memset(mem_data_new + total_size_old,
+    memset(heap_data + total_size_old,
            0, (uint32)total_size - total_size_old);
 
+    module_inst->heap_data.ptr = heap_data;
+    module_inst->heap_handle.ptr = (uint8*)heap_handle_old
+                                   + (heap_data - heap_data_old);
+    module_inst->heap_data_end.ptr = heap_data + heap_size;
+
+    if (mem_allocator_migrate(module_inst->heap_handle.ptr,
+                              heap_handle_old) != 0) {
+        aot_set_exception(module_inst, "fail to enlarge memory.");
+        return false;
+    }
+
     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;
+    module_inst->memory_data_size = (uint32)memory_data_size;
+#if WASM_ENABLE_SPEC_TEST == 0
+    module_inst->total_mem_size = (uint32)(heap_size + memory_data_size);
+#else
+    module_inst->total_mem_size = (uint32)memory_data_size;
+#endif
+    module_inst->memory_data.ptr = (uint8*)heap_data + heap_size;
+    module_inst->memory_data_end.ptr = (uint8*)module_inst->memory_data.ptr
+                                       + (uint32)memory_data_size;
 
+    module_inst->mem_bound_check_1byte = module_inst->total_mem_size - 1;
+    module_inst->mem_bound_check_2bytes = module_inst->total_mem_size - 2;
+    module_inst->mem_bound_check_4bytes = module_inst->total_mem_size - 4;
+    module_inst->mem_bound_check_8bytes = module_inst->total_mem_size - 8;
     return true;
 }
 
@@ -813,7 +825,7 @@ aot_is_wasm_type_equal(AOTModuleInstance *module_inst,
 
 bool
 aot_invoke_native(WASMExecEnv *exec_env, uint32 func_idx,
-                  uint32 *frame_lp, uint32 argc, uint32 *argv_ret)
+                  uint32 argc, uint32 *argv)
 {
     AOTModuleInstance *module_inst = (AOTModuleInstance*)
                             wasm_runtime_get_module_inst(exec_env);
@@ -844,12 +856,12 @@ aot_invoke_native(WASMExecEnv *exec_env, uint32 func_idx,
     if (!import_func->call_conv_raw) {
         return wasm_runtime_invoke_native(exec_env, func_ptr,
                                           func_type, signature, attachment,
-                                          frame_lp, argc, argv_ret);
+                                          argv, argc, argv);
     }
     else {
         return wasm_runtime_invoke_native_raw(exec_env, func_ptr,
                                               func_type, signature, attachment,
-                                              frame_lp, argc, argv_ret);
+                                              argv, argc, argv);
     }
 }
 
@@ -857,7 +869,7 @@ bool
 aot_call_indirect(WASMExecEnv *exec_env,
                   bool check_func_type, uint32 func_type_idx,
                   uint32 table_elem_idx,
-                  uint32 *frame_lp, uint32 argc, uint32 *argv_ret)
+                  uint32 argc, uint32 *argv)
 {
     AOTModuleInstance *module_inst = (AOTModuleInstance*)
                                      wasm_runtime_get_module_inst(exec_env);
@@ -913,11 +925,11 @@ aot_call_indirect(WASMExecEnv *exec_env,
             return wasm_runtime_invoke_native_raw(exec_env, func_ptr,
                                                   func_type, signature,
                                                   attachment,
-                                                  frame_lp, argc, argv_ret);
+                                                  argv, argc, argv);
         }
     }
 
     return wasm_runtime_invoke_native(exec_env, func_ptr,
                                       func_type, signature, attachment,
-                                      frame_lp, argc, argv_ret);
+                                      argv, argc, argv);
 }

+ 13 - 8
core/iwasm/aot/aot_runtime.h

@@ -18,9 +18,6 @@
 extern "C" {
 #endif
 
-#define AOT_MAGIC_NUMBER 0x746f6100
-#define AOT_CURRENT_VERSION 1
-
 typedef enum AOTExceptionID {
     EXCE_UNREACHABLE = 0,
     EXCE_OUT_OF_MEMORY,
@@ -200,19 +197,27 @@ typedef struct AOTModuleInstance {
     /* WASI context */
     AOTPointer wasi_ctx;
 
+    /* total memory size: heap and linear memory */
+    uint32 total_mem_size;
+
+    /* boundary check constants for aot code */
+    uint32 mem_bound_check_1byte;
+    uint32 mem_bound_check_2bytes;
+    uint32 mem_bound_check_4bytes;
+    uint32 mem_bound_check_8bytes;
+
     /* others */
     int32 temp_ret;
     uint32 llvm_stack;
-    int32 DYNAMICTOP_PTR_offset;
     uint32 default_wasm_stack_size;
 
     /* reserved */
-    uint32 reserved[16];
+    uint32 reserved[12];
 
     union {
         uint64 _make_it_8_byte_aligned_;
         uint8 bytes[1];
-    } global_table_heap_data;
+    } global_table_data;
 } AOTModuleInstance;
 
 typedef AOTExportFunc AOTFunctionInstance;
@@ -441,13 +446,13 @@ aot_is_wasm_type_equal(AOTModuleInstance *module_inst,
  */
 bool
 aot_invoke_native(WASMExecEnv *exec_env, uint32 func_idx,
-                  uint32 *frame_lp, uint32 argc, uint32 *argv_ret);
+                  uint32 argc, uint32 *argv);
 
 bool
 aot_call_indirect(WASMExecEnv *exec_env,
                   bool check_func_type, uint32 func_type_idx,
                   uint32 table_elem_idx,
-                  uint32 *frame_lp, uint32 argc, uint32 *argv_ret);
+                  uint32 argc, uint32 *argv);
 
 uint32
 aot_get_plt_table_size();

+ 2 - 0
core/iwasm/common/wasm_native.c

@@ -162,9 +162,11 @@ wasm_native_resolve_symbol(const char *module_name, const char *field_name,
         if (signature && signature[0] != '\0') {
             /* signature is not empty, check its format */
             if (!check_symbol_signature(func_type, signature)) {
+#if WASM_ENABLE_WAMR_COMPILER == 0 /* Output warning except running aot compiler */
                 LOG_WARNING("failed to check signature '%s' and resolve "
                             "pointer params for import function (%s %s)\n",
                             signature, module_name, field_name);
+#endif
                 return NULL;
             }
             else

+ 28 - 11
core/iwasm/common/wasm_runtime_common.c

@@ -810,9 +810,9 @@ wasm_runtime_init_wasi(WASMModuleInstanceCommon *module_inst,
         goto fail;
     }
 
-    wasi_ctx->curfds = curfds;
-    wasi_ctx->prestats = prestats;
-    wasi_ctx->argv_environ = argv_environ;
+    wasi_ctx->curfds_offset = offset_curfds;
+    wasi_ctx->prestats_offset = offset_prestats;
+    wasi_ctx->argv_environ_offset = offset_argv_environ;
 
     fd_table_init(curfds);
     fd_prestats_init(prestats);
@@ -950,14 +950,32 @@ void
 wasm_runtime_destroy_wasi(WASMModuleInstanceCommon *module_inst)
 {
     WASIContext *wasi_ctx = wasm_runtime_get_wasi_ctx(module_inst);
+    struct argv_environ_values *argv_environ;
+    struct fd_table *curfds;
+    struct fd_prestats *prestats;
 
     if (wasi_ctx) {
-        if (wasi_ctx->argv_environ)
-            argv_environ_destroy(wasi_ctx->argv_environ);
-        if (wasi_ctx->curfds)
-            fd_table_destroy(wasi_ctx->curfds);
-        if (wasi_ctx->prestats)
-            fd_prestats_destroy(wasi_ctx->prestats);
+        if (wasi_ctx->argv_environ_offset) {
+            argv_environ = (struct argv_environ_values *)
+                wasm_runtime_addr_app_to_native(module_inst,
+                                                wasi_ctx->argv_environ_offset);
+            argv_environ_destroy(argv_environ);
+            wasm_runtime_module_free(module_inst, wasi_ctx->argv_environ_offset);
+        }
+        if (wasi_ctx->curfds_offset) {
+            curfds = (struct fd_table *)
+                wasm_runtime_addr_app_to_native(module_inst,
+                                                wasi_ctx->curfds_offset);
+            fd_table_destroy(curfds);
+            wasm_runtime_module_free(module_inst, wasi_ctx->curfds_offset);
+        }
+        if (wasi_ctx->prestats_offset) {
+            prestats = (struct fd_prestats *)
+                wasm_runtime_addr_app_to_native(module_inst,
+                                                wasi_ctx->prestats_offset);
+            fd_prestats_destroy(prestats);
+            wasm_runtime_module_free(module_inst, wasi_ctx->prestats_offset);
+        }
         wasm_runtime_free(wasi_ctx);
     }
 }
@@ -2141,8 +2159,7 @@ wasm_runtime_call_indirect(WASMExecEnv *exec_env,
 #if WASM_ENABLE_AOT != 0
     if (exec_env->module_inst->module_type == Wasm_Module_AoT)
         return aot_call_indirect(exec_env, false, 0,
-                                 element_indices,
-                                 argv, argc, argv);
+                                 element_indices, argc, argv);
 #endif
     return false;
 }

+ 7 - 3
core/iwasm/common/wasm_runtime_common.h

@@ -46,9 +46,13 @@ typedef struct WASMModuleInstanceCommon {
 
 #if WASM_ENABLE_LIBC_WASI != 0
 typedef struct WASIContext {
-    struct fd_table *curfds;
-    struct fd_prestats *prestats;
-    struct argv_environ_values *argv_environ;
+    /* Use offset but not native address, since these fields are
+       allocated from app's heap, and the heap space may be re-allocated
+       after memory.grow opcode is executed, the original native address
+       cannot be accessed again. */
+    int32 curfds_offset;
+    int32 prestats_offset;
+    int32 argv_environ_offset;
 } WASIContext;
 #endif
 

+ 2 - 1
core/iwasm/compilation/aot_emit_aot_file.c

@@ -821,13 +821,14 @@ aot_emit_file_header(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
                      AOTCompData *comp_data, AOTObjectData *obj_data)
 {
     uint32 offset = *p_offset;
+    uint32 aot_curr_version = AOT_CURRENT_VERSION;
 
     EMIT_U8('\0');
     EMIT_U8('a');
     EMIT_U8('o');
     EMIT_U8('t');
 
-    EMIT_U32(1);
+    EMIT_U32(aot_curr_version);
 
     *p_offset = offset;
     return true;

+ 53 - 72
core/iwasm/compilation/aot_emit_function.c

@@ -143,20 +143,19 @@ call_aot_invoke_native_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
                             LLVMTypeRef ret_type, uint8 wasm_ret_type,
                             LLVMValueRef *p_value_ret, LLVMValueRef *p_res)
 {
-    LLVMTypeRef func_type, func_ptr_type, func_param_types[5];
+    LLVMTypeRef func_type, func_ptr_type, func_param_types[4];
     LLVMTypeRef ret_ptr_type, elem_ptr_type;
     LLVMValueRef func, elem_idx, elem_ptr;
-    LLVMValueRef func_param_values[5], value_ret = NULL, value_ret_ptr, res;
+    LLVMValueRef func_param_values[4], value_ret = NULL, res;
     char buf[32], *func_name = "aot_invoke_native";
     uint32 i, cell_num = 0;
 
     /* prepare function type of aot_invoke_native */
     func_param_types[0] = comp_ctx->exec_env_type;  /* exec_env */
     func_param_types[1] = I32_TYPE;                 /* func_idx */
-    func_param_types[2] = INT32_PTR_TYPE;           /* frame_lp */
-    func_param_types[3] = I32_TYPE;                 /* argc */
-    func_param_types[4] = INT32_PTR_TYPE;           /* argv_ret */
-    if (!(func_type = LLVMFunctionType(INT8_TYPE, func_param_types, 5, false))) {
+    func_param_types[2] = I32_TYPE;                 /* argc */
+    func_param_types[3] = INT32_PTR_TYPE;           /* argv */
+    if (!(func_type = LLVMFunctionType(INT8_TYPE, func_param_types, 4, false))) {
         aot_set_last_error("llvm add function type failed.");
         return false;
     }
@@ -216,6 +215,24 @@ call_aot_invoke_native_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
         cell_num += wasm_value_type_cell_num(aot_func_type->types[i]);
     }
 
+    func_param_values[0] = func_ctx->exec_env;
+    func_param_values[1] = func_idx;
+    func_param_values[2] = I32_CONST(param_cell_num);
+    func_param_values[3] = func_ctx->argv_buf;
+
+    if (!func_param_values[2]) {
+        aot_set_last_error("llvm create const failed.");
+        return false;
+    }
+
+    /* call aot_invoke_native() function */
+    if (!(res = LLVMBuildCall(comp_ctx->builder, func,
+                              func_param_values, 4, "res"))) {
+        aot_set_last_error("llvm build call failed.");
+        return false;
+    }
+
+    /* get function return value */
     if (wasm_ret_type != VALUE_TYPE_VOID) {
         if (!(ret_ptr_type = LLVMPointerType(ret_type, 0))) {
             aot_set_last_error("llvm add pointer type failed.");
@@ -227,39 +244,12 @@ call_aot_invoke_native_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
             aot_set_last_error("llvm build bit cast failed.");
             return false;
         }
-
-        /* convert to int32 pointer */
-        if (!(value_ret_ptr = LLVMBuildBitCast(comp_ctx->builder, value_ret,
-                                               INT32_PTR_TYPE, "argv_ret_ptr"))) {
-            aot_set_last_error("llvm build store failed.");
+        if (!(*p_value_ret = LLVMBuildLoad(comp_ctx->builder, value_ret,
+                                           "value_ret"))) {
+            aot_set_last_error("llvm build load failed.");
             return false;
         }
     }
-    else {
-        value_ret_ptr = LLVMConstNull(INT32_PTR_TYPE);
-    }
-
-    func_param_values[0] = func_ctx->exec_env;
-    func_param_values[1] = func_idx;
-    func_param_values[2] = func_ctx->argv_buf;
-    func_param_values[3] = I32_CONST(param_cell_num);
-    func_param_values[4] = value_ret_ptr;
-
-    if (!func_param_values[3]) {
-        aot_set_last_error("llvm create const failed.");
-        return false;
-    }
-
-    /* call aot_invoke_native() function */
-    if (!(res = LLVMBuildCall(comp_ctx->builder, func,
-                              func_param_values, 5, "res"))) {
-        aot_set_last_error("llvm build call failed.");
-        return false;
-    }
-
-    if (wasm_ret_type != VALUE_TYPE_VOID)
-        /* get function return value */
-        *p_value_ret = LLVMBuildLoad(comp_ctx->builder, value_ret, "value_ret");
 
     *p_res = res;
     return true;
@@ -395,10 +385,10 @@ call_aot_call_indirect_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
                             LLVMTypeRef ret_type, uint8 wasm_ret_type,
                             LLVMValueRef *p_value_ret, LLVMValueRef *p_res)
 {
-    LLVMTypeRef func_type, func_ptr_type, func_param_types[7];
+    LLVMTypeRef func_type, func_ptr_type, func_param_types[6];
     LLVMTypeRef ret_ptr_type, elem_ptr_type;
     LLVMValueRef func, elem_idx, elem_ptr;
-    LLVMValueRef func_param_values[7], value_ret = NULL, value_ret_ptr, res = NULL;
+    LLVMValueRef func_param_values[6], value_ret = NULL, res = NULL;
     char buf[32], *func_name = "aot_call_indirect";
     uint32 i, cell_num = 0;
 
@@ -407,10 +397,9 @@ call_aot_call_indirect_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
     func_param_types[1] = INT8_TYPE;                /* check_func_type */
     func_param_types[2] = I32_TYPE;                 /* func_type_idx */
     func_param_types[3] = I32_TYPE;                 /* table_elem_idx */
-    func_param_types[4] = INT32_PTR_TYPE;           /* frame_lp */
-    func_param_types[5] = I32_TYPE;                 /* argc */
-    func_param_types[6] = INT32_PTR_TYPE;           /* argv_ret */
-    if (!(func_type = LLVMFunctionType(INT8_TYPE, func_param_types, 7, false))) {
+    func_param_types[4] = I32_TYPE;                 /* argc */
+    func_param_types[5] = INT32_PTR_TYPE;           /* argv */
+    if (!(func_type = LLVMFunctionType(INT8_TYPE, func_param_types, 6, false))) {
         aot_set_last_error("llvm add function type failed.");
         return false;
     }
@@ -470,36 +459,12 @@ call_aot_call_indirect_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
         cell_num += wasm_value_type_cell_num(aot_func_type->types[i]);
     }
 
-    if (wasm_ret_type != VALUE_TYPE_VOID) {
-        if (!(ret_ptr_type = LLVMPointerType(ret_type, 0))) {
-            aot_set_last_error("llvm add pointer type failed.");
-            return false;
-        }
-
-        if (!(value_ret = LLVMBuildBitCast(comp_ctx->builder, func_ctx->argv_buf,
-                                           ret_ptr_type, "argv_ret"))) {
-            aot_set_last_error("llvm build bit cast failed.");
-            return false;
-        }
-
-        /* convert to int32 pointer */
-        if (!(value_ret_ptr = LLVMBuildBitCast(comp_ctx->builder, value_ret,
-                                               INT32_PTR_TYPE, "argv_ret_ptr"))) {
-            aot_set_last_error("llvm build store failed.");
-            return false;
-        }
-    }
-    else {
-        value_ret_ptr = LLVMConstNull(INT32_PTR_TYPE);
-    }
-
     func_param_values[0] = func_ctx->exec_env;
     func_param_values[1] = I8_CONST(true);
     func_param_values[2] = func_type_idx;
     func_param_values[3] = table_elem_idx;
-    func_param_values[4] = func_ctx->argv_buf;
-    func_param_values[5] = I32_CONST(param_cell_num);
-    func_param_values[6] = value_ret_ptr;
+    func_param_values[4] = I32_CONST(param_cell_num);
+    func_param_values[5] = func_ctx->argv_buf;
 
     if (!func_param_values[1] || !func_param_values[4]) {
         aot_set_last_error("llvm create const failed.");
@@ -508,14 +473,30 @@ call_aot_call_indirect_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
 
     /* call aot_call_indirect() function */
     if (!(res = LLVMBuildCall(comp_ctx->builder, func,
-                              func_param_values, 7, "res"))) {
+                              func_param_values, 6, "res"))) {
         aot_set_last_error("llvm build call failed.");
         return false;
     }
 
-    if (wasm_ret_type != VALUE_TYPE_VOID)
-        /* get function return value */
-        *p_value_ret = LLVMBuildLoad(comp_ctx->builder, value_ret, "value_ret");
+    /* get function return value */
+    if (wasm_ret_type != VALUE_TYPE_VOID) {
+        if (!(ret_ptr_type = LLVMPointerType(ret_type, 0))) {
+            aot_set_last_error("llvm add pointer type failed.");
+            return false;
+        }
+
+        if (!(value_ret = LLVMBuildBitCast(comp_ctx->builder, func_ctx->argv_buf,
+                                           ret_ptr_type, "argv_ret"))) {
+            aot_set_last_error("llvm build bit cast failed.");
+            return false;
+        }
+
+        if (!(*p_value_ret = LLVMBuildLoad(comp_ctx->builder, value_ret,
+                                           "value_ret"))) {
+            aot_set_last_error("llvm build load failed.");
+            return false;
+        }
+    }
 
     *p_res = res;
     return true;

+ 102 - 148
core/iwasm/compilation/aot_emit_memory.c

@@ -23,14 +23,6 @@
     }                                                   \
   } while (0)
 
-#define BUILD_COND_BR(cmp_val, then_block, else_block) do { \
-    if (!LLVMBuildCondBr(comp_ctx->builder, cmp_val,        \
-                         then_block, else_block)) {         \
-        aot_set_last_error("llvm build cond br failed.");   \
-        goto fail;                                          \
-    }                                                       \
-  } while (0)
-
 #define ADD_BASIC_BLOCK(block, name) do {                           \
     if (!(block = LLVMAppendBasicBlockInContext(comp_ctx->context,  \
                                                 func_ctx->func,     \
@@ -43,53 +35,88 @@
 #define SET_BUILD_POS(block)    \
     LLVMPositionBuilderAtEnd(comp_ctx->builder, block)
 
+static LLVMValueRef
+get_memory_check_bound(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+                       uint32 bytes)
+{
+    LLVMValueRef mem_check_bound = NULL;
+    switch (bytes) {
+        case 1:
+            mem_check_bound = func_ctx->mem_bound_check_1byte;
+            break;
+        case 2:
+            mem_check_bound = func_ctx->mem_bound_check_2bytes;
+            break;
+        case 4:
+            mem_check_bound = func_ctx->mem_bound_check_4bytes;
+            break;
+        case 8:
+            mem_check_bound = func_ctx->mem_bound_check_8bytes;
+            break;
+        default:
+            bh_assert(0);
+            return NULL;
+    }
+
+    if (func_ctx->mem_space_unchanged)
+        return mem_check_bound;
+
+    if (!(mem_check_bound = LLVMBuildLoad(comp_ctx->builder,
+                                          mem_check_bound,
+                                          "mem_check_bound"))) {
+        aot_set_last_error("llvm build load failed.");
+        return NULL;
+    }
+    return mem_check_bound;
+}
+
 static LLVMValueRef
 check_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
                       uint32 offset, uint32 bytes)
 {
     LLVMValueRef offset_const = I32_CONST(offset);
-    LLVMValueRef size_const = I32_CONST(bytes);
-    LLVMValueRef addr, maddr, moffset;
-    LLVMValueRef cmp, phi;
-    LLVMValueRef mem_base_addr, mem_data_size;
-    LLVMValueRef heap_base_addr, heap_base_offset;
-    LLVMValueRef mem_offset_max = NULL, heap_offset_max = NULL;
-    LLVMBasicBlockRef check_mem_space, check_heap_space, check_succ;
+    LLVMValueRef bytes_const = I32_CONST(bytes);
+    LLVMValueRef bytes64_const = I64_CONST(bytes);
+    LLVMValueRef heap_base_offset = func_ctx->heap_base_offset;
+    LLVMValueRef addr, maddr, offset1, offset2, cmp;
+    LLVMValueRef mem_base_addr, mem_check_bound, total_mem_size;
     LLVMBasicBlockRef block_curr = LLVMGetInsertBlock(comp_ctx->builder);
+    LLVMBasicBlockRef check_succ, check_mem_space;
 
     CHECK_LLVM_CONST(offset_const);
-    CHECK_LLVM_CONST(size_const);
+    CHECK_LLVM_CONST(bytes_const);
+    CHECK_LLVM_CONST(bytes64_const);
 
-    heap_base_addr = func_ctx->heap_base_addr;
-    heap_base_offset = func_ctx->heap_base_offset;
+    /* Get memory base address and memory data size */
+    if (func_ctx->mem_space_unchanged) {
+        mem_base_addr = func_ctx->mem_base_addr;
+    }
+    else {
+        if (!(mem_base_addr = LLVMBuildLoad(comp_ctx->builder,
+                                            func_ctx->mem_base_addr,
+                                            "mem_base"))) {
+            aot_set_last_error("llvm build load failed.");
+            goto fail;
+        }
+    }
 
     POP_I32(addr);
-    BUILD_OP(Add, offset_const, addr, moffset, "moffset");
+    /* offset1 = offset + addr; */
+    BUILD_OP(Add, offset_const, addr, offset1, "offset1");
 
     /* return addres directly if constant offset and inside memory space */
-    if (LLVMIsConstant(moffset)) {
-        uint32 memory_offset = (uint32)LLVMConstIntGetZExtValue(moffset);
+    if (LLVMIsConstant(offset1)) {
+        uint32 mem_offset = (uint32)LLVMConstIntGetZExtValue(offset1);
+        uint32 num_bytes_per_page = comp_ctx->comp_data->num_bytes_per_page;
         uint32 init_page_count = comp_ctx->comp_data->mem_init_page_count;
-        if (init_page_count > 0
-            && memory_offset <= comp_ctx->comp_data->num_bytes_per_page
-                                * init_page_count - bytes) {
+        uint32 mem_data_size = num_bytes_per_page * init_page_count;
+        if (mem_data_size > 0
+            && mem_offset <= mem_data_size - bytes) {
             /* inside memory space */
-            if (!func_ctx->mem_space_unchanged) {
-                if (!(mem_base_addr = LLVMBuildLoad(comp_ctx->builder,
-                                func_ctx->mem_base_addr,
-                                "mem_base"))) {
-                    aot_set_last_error("llvm build load failed.");
-                    return NULL;
-                }
-            }
-            else {
-                mem_base_addr = func_ctx->mem_base_addr;
-            }
-
             /* maddr = mem_base_addr + moffset */
             if (!(maddr = LLVMBuildInBoundsGEP(comp_ctx->builder,
                                                mem_base_addr,
-                                               &moffset, 1, "maddr"))) {
+                                               &offset1, 1, "maddr"))) {
                 aot_set_last_error("llvm build add failed.");
                 goto fail;
             }
@@ -97,136 +124,63 @@ check_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
         }
     }
 
-    /* Add basic blocks */
-    ADD_BASIC_BLOCK(check_heap_space, "check_heap_space");
-    ADD_BASIC_BLOCK(check_succ, "check_succ");
-
-    LLVMMoveBasicBlockAfter(check_heap_space, block_curr);
-    LLVMMoveBasicBlockAfter(check_succ, check_heap_space);
-
-    /* Add return maddress phi for check_succ block */
-    SET_BUILD_POS(check_succ);
-    if (!(phi = LLVMBuildPhi(comp_ctx->builder,
-                             INT8_PTR_TYPE, "maddr_phi"))) {
-        aot_set_last_error("llvm build phi failed.");
-        goto fail;
-    }
-    SET_BUILD_POS(block_curr);
-
-    /* Get memory data size */
-    if (!func_ctx->mem_space_unchanged) {
-        if (!(mem_data_size = LLVMBuildLoad(comp_ctx->builder,
-                                            func_ctx->mem_data_size,
-                                            "mem_data_size"))) {
-            aot_set_last_error("llvm build load failed.");
-            return NULL;
+    if (comp_ctx->comp_data->mem_init_page_count == 0) {
+        /* Get total memory size */
+        if (func_ctx->mem_space_unchanged) {
+            total_mem_size = func_ctx->total_mem_size;
+        }
+        else {
+            if (!(total_mem_size = LLVMBuildLoad(comp_ctx->builder,
+                                                 func_ctx->total_mem_size,
+                                                 "total_mem_size"))) {
+                aot_set_last_error("llvm build load failed.");
+                goto fail;
+            }
         }
-    }
-    else {
-        mem_data_size = func_ctx->mem_data_size;
-    }
 
-    if (comp_ctx->comp_data->mem_init_page_count == 0) {
         ADD_BASIC_BLOCK(check_mem_space, "check_mem_space");
         LLVMMoveBasicBlockAfter(check_mem_space, block_curr);
 
-        /* if mem_data_size is zero, check heap space */
-        BUILD_ICMP(LLVMIntEQ, mem_data_size, I32_ZERO, cmp,
-                   "cmp_mem_data_size");
-        BUILD_COND_BR(cmp, check_heap_space, check_mem_space);
+        /* if total_mem_size is zero, boundary check fail */
+        BUILD_ICMP(LLVMIntEQ, total_mem_size, I32_ZERO, cmp,
+                   "cmp_total_mem_size");
+        if (!aot_emit_exception(comp_ctx, func_ctx,
+                                EXCE_OUT_OF_BOUNDS_MEMORY_ACCESS,
+                                true, cmp, check_mem_space)) {
+            goto fail;
+        }
         SET_BUILD_POS(check_mem_space);
     }
 
-    /* Get memory base address */
-    if (!func_ctx->mem_space_unchanged) {
-        if (!(mem_base_addr = LLVMBuildLoad(comp_ctx->builder,
-                                            func_ctx->mem_base_addr,
-                                            "mem_base"))) {
-            aot_set_last_error("llvm build load failed.");
-            return NULL;
-        }
-    }
-    else {
-        mem_base_addr = func_ctx->mem_base_addr;
-    }
+    /* offset2 = offset1 - heap_base_offset; */
+    BUILD_OP(Sub, offset1, heap_base_offset, offset2, "offset2");
 
-    /* maddr = mem_base_addr + moffset */
-    if (!(maddr = LLVMBuildInBoundsGEP(comp_ctx->builder, mem_base_addr,
-                                       &moffset, 1, "maddr"))) {
-        aot_set_last_error("llvm build add failed.");
+    if (!(mem_check_bound =
+                get_memory_check_bound(comp_ctx, func_ctx, bytes))) {
         goto fail;
     }
-    block_curr = LLVMGetInsertBlock(comp_ctx->builder);
-    LLVMAddIncoming(phi, &maddr, &block_curr, 1);
-
-    if (!func_ctx->mem_space_unchanged) {
-        /* mem_offset_max = mem_data_size - bytes to load/read */
-        if (!(mem_offset_max = LLVMBuildSub(comp_ctx->builder,
-                                            mem_data_size, size_const,
-                                            "mem_offset_max"))) {
-            aot_set_last_error("llvm build sub failed.");
-            goto fail;
-        }
-    }
-    else {
-        if (bytes == 1)
-            mem_offset_max = func_ctx->mem_bound_1_byte;
-        else if (bytes == 2)
-            mem_offset_max = func_ctx->mem_bound_2_bytes;
-        else if (bytes == 4)
-            mem_offset_max = func_ctx->mem_bound_4_bytes;
-        else if (bytes == 8)
-            mem_offset_max = func_ctx->mem_bound_8_bytes;
-    }
-
-    /* in linear memory if (uint32)moffset <= (uint32)mem_offset_max,
-       else check heap space */
-    BUILD_ICMP(LLVMIntULE, moffset, mem_offset_max, cmp, "cmp_mem_offset");
 
-    /* Create condtion br */
-    BUILD_COND_BR(cmp, check_succ, check_heap_space);
-
-    /* Start to translate the check_heap_space block */
-    SET_BUILD_POS(check_heap_space);
+    /* Add basic blocks */
+    ADD_BASIC_BLOCK(check_succ, "check_succ");
+    LLVMMoveBasicBlockAfter(check_succ, block_curr);
 
-    /* moffset -= heap_base_offset */
-    if (!(moffset = LLVMBuildSub(comp_ctx->builder,
-                                 moffset, heap_base_offset,
-                                 "moffset_to_heap"))) {
-        aot_set_last_error("llvm build sub failed.");
+    /* offset2 > bound ? */
+    BUILD_ICMP(LLVMIntUGT, offset2, mem_check_bound, cmp, "cmp");
+    if (!aot_emit_exception(comp_ctx, func_ctx,
+                            EXCE_OUT_OF_BOUNDS_MEMORY_ACCESS,
+                            true, cmp, check_succ)) {
         goto fail;
     }
 
-    /* maddr = heap_base_addr + moffset */
-    if (!(maddr = LLVMBuildInBoundsGEP(comp_ctx->builder, heap_base_addr,
-                                       &moffset, 1, "maddr"))) {
+    SET_BUILD_POS(check_succ);
+
+    /* maddr = mem_base_addr + offset1 */
+    if (!(maddr = LLVMBuildInBoundsGEP(comp_ctx->builder, mem_base_addr,
+                                       &offset1, 1, "maddr"))) {
         aot_set_last_error("llvm build add failed.");
         goto fail;
     }
-    block_curr = LLVMGetInsertBlock(comp_ctx->builder);
-    LLVMAddIncoming(phi, &maddr, &block_curr, 1);
-
-    /* heap space base addr and size is unchanged,
-       the heap boundary is unchanged also. */
-    if (bytes == 1)
-        heap_offset_max = func_ctx->heap_bound_1_byte;
-    else if (bytes == 2)
-        heap_offset_max = func_ctx->heap_bound_2_bytes;
-    else if (bytes == 4)
-        heap_offset_max = func_ctx->heap_bound_4_bytes;
-    else if (bytes == 8)
-        heap_offset_max = func_ctx->heap_bound_8_bytes;
-
-    /* in heap space if (uint32)moffset <= (uint32)heap_offset_max,
-       else throw exception */
-    BUILD_ICMP(LLVMIntUGT, moffset, heap_offset_max, cmp, "cmp_heap_offset");
-    if (!aot_emit_exception(comp_ctx, func_ctx,
-                            EXCE_OUT_OF_BOUNDS_MEMORY_ACCESS,
-                            true, cmp, check_succ))
-        goto fail;
-
-    SET_BUILD_POS(check_succ);
-    return phi;
+    return maddr;
 fail:
     return NULL;
 }

+ 1 - 1
core/iwasm/compilation/aot_emit_variable.c

@@ -105,7 +105,7 @@ compile_global(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
     AOTCompData *comp_data = comp_ctx->comp_data;
     uint32 import_global_count = comp_data->import_global_count;
     uint32 global_base_offset = offsetof(AOTModuleInstance,
-                                         global_table_heap_data.bytes);
+                                         global_table_data.bytes);
     uint32 global_offset;
     uint8 global_type;
     LLVMValueRef offset, global_ptr, global;

+ 89 - 79
core/iwasm/compilation/aot_llvm.c

@@ -181,68 +181,117 @@ create_memory_info(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
         }
     }
 
-    /* Load memory data size */
-    offset = I32_CONST(offsetof(AOTModuleInstance, memory_data_size));
-    if (!(func_ctx->mem_data_size =
+    /* Load total memory size */
+    offset = I32_CONST(offsetof(AOTModuleInstance, total_mem_size));
+    if (!(func_ctx->total_mem_size =
                 LLVMBuildInBoundsGEP(comp_ctx->builder, func_ctx->aot_inst,
-                                     &offset, 1, "mem_data_size_offset"))) {
+                                     &offset, 1, "bound_check_1byte_offset"))) {
         aot_set_last_error("llvm build in bounds gep failed");
         return false;
     }
-    if (!(func_ctx->mem_data_size =
-                LLVMBuildBitCast(comp_ctx->builder, func_ctx->mem_data_size,
-                                 INT32_PTR_TYPE, "mem_data_size_ptr"))) {
+    if (!(func_ctx->total_mem_size =
+                LLVMBuildBitCast(comp_ctx->builder, func_ctx->total_mem_size,
+                                 INT32_PTR_TYPE, "bound_check_1byte_ptr"))) {
         aot_set_last_error("llvm build bit cast failed");
         return false;
     }
     if (mem_space_unchanged) {
-        if (!(func_ctx->mem_data_size =
-                    LLVMBuildLoad(comp_ctx->builder, func_ctx->mem_data_size,
-                                  "mem_data_size"))) {
+        if (!(func_ctx->total_mem_size =
+                    LLVMBuildLoad(comp_ctx->builder, func_ctx->total_mem_size,
+                                  "bound_check_1byte"))) {
             aot_set_last_error("llvm build load failed");
             return false;
         }
-        if (!(func_ctx->mem_bound_1_byte =
-                    LLVMBuildSub(comp_ctx->builder,
-                                 func_ctx->mem_data_size, I32_ONE,
-                                 "mem_bound_1_byte"))
-            || !(func_ctx->mem_bound_2_bytes =
-                    LLVMBuildSub(comp_ctx->builder,
-                                 func_ctx->mem_data_size, I32_TWO,
-                                 "mem_bound_2_bytes"))
-            || !(func_ctx->mem_bound_4_bytes =
-                    LLVMBuildSub(comp_ctx->builder,
-                                 func_ctx->mem_data_size, I32_FOUR,
-                                 "mem_bound_4_bytes"))
-            || !(func_ctx->mem_bound_8_bytes =
-                    LLVMBuildSub(comp_ctx->builder,
-                                 func_ctx->mem_data_size, I32_EIGHT,
-                                 "mem_bound_8_bytes"))) {
-            aot_set_last_error("llvm build sub failed");
+    }
+
+    /* Load memory bound check constants */
+    offset = I32_CONST(offsetof(AOTModuleInstance, mem_bound_check_1byte));
+    if (!(func_ctx->mem_bound_check_1byte =
+                LLVMBuildInBoundsGEP(comp_ctx->builder, func_ctx->aot_inst,
+                                     &offset, 1, "bound_check_1byte_offset"))) {
+        aot_set_last_error("llvm build in bounds gep failed");
+        return false;
+    }
+    if (!(func_ctx->mem_bound_check_1byte =
+                LLVMBuildBitCast(comp_ctx->builder, func_ctx->mem_bound_check_1byte,
+                                 INT32_PTR_TYPE, "bound_check_1byte_ptr"))) {
+        aot_set_last_error("llvm build bit cast failed");
+        return false;
+    }
+    if (mem_space_unchanged) {
+        if (!(func_ctx->mem_bound_check_1byte =
+                    LLVMBuildLoad(comp_ctx->builder, func_ctx->mem_bound_check_1byte,
+                                  "bound_check_1byte"))) {
+            aot_set_last_error("llvm build load failed");
             return false;
         }
     }
 
-    /* Load heap base address */
-    offset = I32_CONST(offsetof(AOTModuleInstance, heap_data.ptr));
-    if (!(func_ctx->heap_base_addr =
+    offset = I32_CONST(offsetof(AOTModuleInstance, mem_bound_check_2bytes));
+    if (!(func_ctx->mem_bound_check_2bytes =
                 LLVMBuildInBoundsGEP(comp_ctx->builder, func_ctx->aot_inst,
-                                     &offset, 1, "heap_base_addr_offset"))) {
+                                     &offset, 1, "bound_check_2bytes_offset"))) {
         aot_set_last_error("llvm build in bounds gep failed");
         return false;
     }
-    if (!(func_ctx->heap_base_addr =
-                LLVMBuildBitCast(comp_ctx->builder, func_ctx->heap_base_addr,
-                                 int8_ptr_type, "heap_base_addr_tmp"))) {
+    if (!(func_ctx->mem_bound_check_2bytes =
+                LLVMBuildBitCast(comp_ctx->builder, func_ctx->mem_bound_check_2bytes,
+                                 INT32_PTR_TYPE, "bound_check_2bytes_ptr"))) {
         aot_set_last_error("llvm build bit cast failed");
         return false;
     }
-    if (!(func_ctx->heap_base_addr =
-                LLVMBuildLoad(comp_ctx->builder, func_ctx->heap_base_addr,
-                              "heap_base_addr"))) {
-        aot_set_last_error("llvm build load failed");
+    if (mem_space_unchanged) {
+        if (!(func_ctx->mem_bound_check_2bytes =
+                    LLVMBuildLoad(comp_ctx->builder, func_ctx->mem_bound_check_2bytes,
+                                  "bound_check_2bytes"))) {
+            aot_set_last_error("llvm build load failed");
+            return false;
+        }
+    }
+
+    offset = I32_CONST(offsetof(AOTModuleInstance, mem_bound_check_4bytes));
+    if (!(func_ctx->mem_bound_check_4bytes =
+                LLVMBuildInBoundsGEP(comp_ctx->builder, func_ctx->aot_inst,
+                                     &offset, 1, "bound_check_4bytes_offset"))) {
+        aot_set_last_error("llvm build in bounds gep failed");
+        return false;
+    }
+    if (!(func_ctx->mem_bound_check_4bytes =
+                LLVMBuildBitCast(comp_ctx->builder, func_ctx->mem_bound_check_4bytes,
+                                 INT32_PTR_TYPE, "bound_check_4bytes_ptr"))) {
+        aot_set_last_error("llvm build bit cast failed");
+        return false;
+    }
+    if (mem_space_unchanged) {
+        if (!(func_ctx->mem_bound_check_4bytes =
+                    LLVMBuildLoad(comp_ctx->builder, func_ctx->mem_bound_check_4bytes,
+                                  "bound_check_4bytes"))) {
+            aot_set_last_error("llvm build load failed");
+            return false;
+        }
+    }
+
+    offset = I32_CONST(offsetof(AOTModuleInstance, mem_bound_check_8bytes));
+    if (!(func_ctx->mem_bound_check_8bytes =
+                LLVMBuildInBoundsGEP(comp_ctx->builder, func_ctx->aot_inst,
+                                     &offset, 1, "bound_check_8bytes_offset"))) {
+        aot_set_last_error("llvm build in bounds gep failed");
+        return false;
+    }
+    if (!(func_ctx->mem_bound_check_8bytes =
+                LLVMBuildBitCast(comp_ctx->builder, func_ctx->mem_bound_check_8bytes,
+                                 INT32_PTR_TYPE, "bound_check_8bytes_ptr"))) {
+        aot_set_last_error("llvm build bit cast failed");
         return false;
     }
+    if (mem_space_unchanged) {
+        if (!(func_ctx->mem_bound_check_8bytes =
+                    LLVMBuildLoad(comp_ctx->builder, func_ctx->mem_bound_check_8bytes,
+                                  "bound_check_8bytes"))) {
+            aot_set_last_error("llvm build load failed");
+            return false;
+        }
+    }
 
     /* Load heap base offset */
     offset = I32_CONST(offsetof(AOTModuleInstance, heap_base_offset));
@@ -265,46 +314,6 @@ create_memory_info(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
         return false;
     }
 
-    /* Load heap data size */
-    offset = I32_CONST(offsetof(AOTModuleInstance, heap_data_size));
-    if (!(func_ctx->heap_data_size =
-                LLVMBuildInBoundsGEP(comp_ctx->builder, func_ctx->aot_inst,
-                                     &offset, 1, "heap_data_size_offset"))) {
-        aot_set_last_error("llvm build in bounds gep failed");
-        return false;
-    }
-    if (!(func_ctx->heap_data_size =
-                LLVMBuildBitCast(comp_ctx->builder, func_ctx->heap_data_size,
-                                 INT32_PTR_TYPE, "heap_data_size_tmp"))) {
-        aot_set_last_error("llvm build bit cast failed");
-        return false;
-    }
-    if (!(func_ctx->heap_data_size =
-                LLVMBuildLoad(comp_ctx->builder, func_ctx->heap_data_size,
-                              "heap_data_size"))) {
-        aot_set_last_error("llvm build load failed");
-        return false;
-    }
-    if (!(func_ctx->heap_bound_1_byte =
-                LLVMBuildSub(comp_ctx->builder,
-                             func_ctx->heap_data_size, I32_ONE,
-                             "heap_bound_1_byte"))
-            || !(func_ctx->heap_bound_2_bytes =
-                LLVMBuildSub(comp_ctx->builder,
-                             func_ctx->heap_data_size, I32_TWO,
-                             "heap_bound_2_bytes"))
-            || !(func_ctx->heap_bound_4_bytes =
-                LLVMBuildSub(comp_ctx->builder,
-                             func_ctx->heap_data_size, I32_FOUR,
-                             "heap_bound_4_bytes"))
-            || !(func_ctx->heap_bound_8_bytes =
-                LLVMBuildSub(comp_ctx->builder,
-                             func_ctx->heap_data_size, I32_EIGHT,
-                             "heap_bound_8_bytes"))) {
-        aot_set_last_error("llvm build sub failed");
-        return false;
-    }
-
     return true;
 }
 
@@ -313,7 +322,7 @@ create_table_base(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
 {
     LLVMValueRef offset;
 
-    offset = I32_CONST(offsetof(AOTModuleInstance, global_table_heap_data.bytes)
+    offset = I32_CONST(offsetof(AOTModuleInstance, global_table_data.bytes)
                        + comp_ctx->comp_data->global_data_size);
     func_ctx->table_base = LLVMBuildInBoundsGEP(comp_ctx->builder,
                                                 func_ctx->aot_inst,
@@ -918,6 +927,7 @@ aot_create_comp_context(AOTCompData *comp_data,
         /* Create LLVM execution engine */
         LLVMInitializeMCJITCompilerOptions(&jit_options, sizeof(jit_options));
         jit_options.OptLevel = LLVMCodeGenLevelAggressive;
+        jit_options.EnableFastISel = true;
         /*jit_options.CodeModel = LLVMCodeModelSmall;*/
         if (LLVMCreateMCJITCompilerForModule
                 (&comp_ctx->exec_engine, comp_ctx->module,

+ 6 - 13
core/iwasm/compilation/aot_llvm.h

@@ -94,20 +94,13 @@ typedef struct AOTFuncContext {
   LLVMValueRef table_base;
   LLVMValueRef argv_buf;
 
-  LLVMValueRef mem_data_size;
-  LLVMValueRef mem_base_addr;
-  LLVMValueRef mem_bound_1_byte;
-  LLVMValueRef mem_bound_2_bytes;
-  LLVMValueRef mem_bound_4_bytes;
-  LLVMValueRef mem_bound_8_bytes;
-
   LLVMValueRef heap_base_offset;
-  LLVMValueRef heap_base_addr;
-  LLVMValueRef heap_data_size;
-  LLVMValueRef heap_bound_1_byte;
-  LLVMValueRef heap_bound_2_bytes;
-  LLVMValueRef heap_bound_4_bytes;
-  LLVMValueRef heap_bound_8_bytes;
+  LLVMValueRef mem_base_addr;
+  LLVMValueRef total_mem_size;
+  LLVMValueRef mem_bound_check_1byte;
+  LLVMValueRef mem_bound_check_2bytes;
+  LLVMValueRef mem_bound_check_4bytes;
+  LLVMValueRef mem_bound_check_8bytes;
 
   LLVMValueRef cur_exception;
 

+ 16 - 25
core/iwasm/interpreter/wasm_interp_classic.c

@@ -223,28 +223,17 @@ LOAD_I16(void *addr)
 
 #endif  /* WASM_CPU_SUPPORTS_UNALIGNED_64BIT_ACCESS != 0 */
 
-#define CHECK_MEMORY_OVERFLOW() do {                                            \
-    uint64 offset1 = offset + addr;                                             \
-    /* if (flags != 2)                                                          \
-      LOG_VERBOSE("unaligned load/store in wasm interp, flag: %d.\n", flags); */\
-    /* The WASM spec doesn't require that the dynamic address operand must be   \
-       unsigned, so we don't check whether integer overflow or not here. */     \
-    /* if (offset1 < offset)                                                    \
-      goto out_of_bounds; */                                                    \
-    if (offset1 + LOAD_SIZE[opcode - WASM_OP_I32_LOAD] <= memory_data_size) {   \
-      /* If offset1 is in valid range, maddr must also be in valid range,       \
-         no need to check it again. */                                          \
-      maddr = memory->memory_data + offset1;                                    \
-    }                                                                           \
-    else if (offset1 > DEFAULT_APP_HEAP_BASE_OFFSET                             \
-             && (offset1 + LOAD_SIZE[opcode - WASM_OP_I32_LOAD] <=              \
-                    DEFAULT_APP_HEAP_BASE_OFFSET + heap_data_size)) {           \
-      /* If offset1 is in valid range, maddr must also be in valid range,       \
-         no need to check it again. */                                          \
-      maddr = memory->heap_data + offset1 - memory->heap_base_offset;           \
-    }                                                                           \
-    else                                                                        \
-      goto out_of_bounds;                                                       \
+#define CHECK_MEMORY_OVERFLOW(bytes) do {                                   \
+    int32 offset1 = (int32)(offset + addr);                                 \
+    uint64 offset2 = (uint64)(uint32)(offset1 - heap_base_offset);          \
+    /* if (flags != 2)                                                      \
+      LOG_VERBOSE("unaligned load/store, flag: %d.\n", flags); */           \
+    if (offset2 + LOAD_SIZE[opcode - WASM_OP_I32_LOAD] <= total_mem_size)   \
+      /* If offset1 is in valid range, maddr must also be in valid range,   \
+         no need to check it again. */                                      \
+      maddr = memory->memory_data + offset1;                                \
+    else                                                                    \
+      goto out_of_bounds;                                                   \
   } while (0)
 
 static inline uint32
@@ -798,9 +787,10 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                                WASMInterpFrame *prev_frame)
 {
   WASMMemoryInstance *memory = module->default_memory;
+  int32 heap_base_offset = memory ? memory->heap_base_offset : 0;
   uint32 num_bytes_per_page = memory ? memory->num_bytes_per_page : 0;
-  uint32 memory_data_size = memory ? num_bytes_per_page * memory->cur_page_count : 0;
-  uint32 heap_data_size = memory ? (uint32)(memory->heap_data_end - memory->heap_data) : 0;
+  uint32 total_mem_size = memory ? num_bytes_per_page * memory->cur_page_count
+                                   - heap_base_offset : 0;
   uint8 *global_data = memory ? memory->global_data : NULL;
   WASMTableInstance *table = module->default_table;
   WASMGlobalInstance *globals = module->globals;
@@ -1419,7 +1409,8 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
           PUSH_I32(prev_page_count);
           /* update the memory instance ptr */
           memory = module->default_memory;
-          memory_data_size = num_bytes_per_page * memory->cur_page_count;
+          total_mem_size = num_bytes_per_page * memory->cur_page_count
+                           - heap_base_offset;
           global_data = memory->global_data;
         }
 

+ 66 - 29
core/iwasm/interpreter/wasm_interp_fast.c

@@ -225,28 +225,17 @@ LOAD_I16(void *addr)
 
 #endif  /* WASM_CPU_SUPPORTS_UNALIGNED_64BIT_ACCESS != 0 */
 
-#define CHECK_MEMORY_OVERFLOW(bytes) do {                                  \
-    uint64 offset1 = offset + addr;                                             \
-    /* if (flags != 2)                                                          \
-      LOG_VERBOSE("unaligned load/store in wasm interp, flag: %d.\n", flags); */\
-    /* The WASM spec doesn't require that the dynamic address operand must be   \
-       unsigned, so we don't check whether integer overflow or not here. */     \
-    /* if (offset1 < offset)                                                    \
-      goto out_of_bounds; */                                                    \
-    if (offset1 + bytes <= memory_data_size) {                                  \
-      /* If offset1 is in valid range, maddr must also be in valid range,       \
-         no need to check it again. */                                          \
-      maddr = memory->memory_data + offset1;                                    \
-    }                                                                           \
-    else if (offset1 > DEFAULT_APP_HEAP_BASE_OFFSET                             \
-             && (offset1 + bytes <=                                             \
-                    DEFAULT_APP_HEAP_BASE_OFFSET + heap_data_size)) {           \
-      /* If offset1 is in valid range, maddr must also be in valid range,       \
-         no need to check it again. */                                          \
-      maddr = memory->heap_data + offset1 - DEFAULT_APP_HEAP_BASE_OFFSET;       \
-    }                                                                           \
-    else                                                                        \
-      goto out_of_bounds;                                                       \
+#define CHECK_MEMORY_OVERFLOW(bytes) do {                                \
+    int32 offset1 = (int32)(offset + addr);                              \
+    uint64 offset2 = (uint64)(uint32)(offset1 - heap_base_offset);       \
+    /* if (flags != 2)                                                   \
+      LOG_VERBOSE("unaligned load/store, flag: %d.\n", flags); */        \
+    if (offset2 + bytes <= total_mem_size)                               \
+      /* If offset1 is in valid range, maddr must also be in valid range,\
+         no need to check it again. */                                   \
+      maddr = memory->memory_data + offset1;                             \
+    else                                                                 \
+      goto out_of_bounds;                                                \
   } while (0)
 
 static inline uint32
@@ -501,10 +490,18 @@ read_leb(const uint8 *buf, uint32 *p_offset, uint32 maxbits, bool sign)
     frame_ip += 6;                                                          \
   } while (0)
 
+#if defined(BUILD_TARGET_X86_32)
+#define DEF_OP_REINTERPRET(src_type) do {                                   \
+    void *src = frame_lp + GET_OFFSET();                                    \
+    void *dst = frame_lp + GET_OFFSET();                                    \
+    bh_memcpy_s(dst, sizeof(src_type), src, sizeof(src_type));              \
+  } while (0)
+#else
 #define DEF_OP_REINTERPRET(src_type) do {                                   \
     SET_OPERAND(src_type, 2, GET_OPERAND(src_type, 0));                     \
     frame_ip += 4;                                                          \
   } while (0)
+#endif
 
 #if WASM_CPU_SUPPORTS_UNALIGNED_64BIT_ACCESS != 0
 #define DEF_OP_NUMERIC_64 DEF_OP_NUMERIC
@@ -779,9 +776,10 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                                WASMInterpFrame *prev_frame)
 {
   WASMMemoryInstance *memory = module->default_memory;
+  int32 heap_base_offset = memory ? memory->heap_base_offset : 0;
   uint32 num_bytes_per_page = memory ? memory->num_bytes_per_page : 0;
-  uint32 memory_data_size = memory ? num_bytes_per_page * memory->cur_page_count : 0;
-  uint32 heap_data_size = memory ? (uint32)(memory->heap_data_end - memory->heap_data) : 0;
+  uint32 total_mem_size = memory ? num_bytes_per_page * memory->cur_page_count
+                                   - heap_base_offset : 0;
   uint8 *global_data = memory ? memory->global_data : NULL;
   WASMTableInstance *table = module->default_table;
   WASMGlobalInstance *globals = module->globals;
@@ -929,10 +927,24 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
           addr2 = GET_OFFSET();
           addr_ret = GET_OFFSET();
 
-          if (!cond)
+          if (!cond) {
+#if defined(BUILD_TARGET_X86_32)
+            if (addr_ret != addr1)
+              bh_memcpy_s(frame_lp + addr_ret, sizeof(int32),
+                          frame_lp + addr1, sizeof(int32));
+#else
             frame_lp[addr_ret] = frame_lp[addr1];
-          else
+#endif
+          }
+          else {
+#if defined(BUILD_TARGET_X86_32)
+            if (addr_ret != addr2)
+              bh_memcpy_s(frame_lp + addr_ret, sizeof(int32),
+                          frame_lp + addr2, sizeof(int32));
+#else
             frame_lp[addr_ret] = frame_lp[addr2];
+#endif
+          }
           HANDLE_OP_END ();
         }
 
@@ -943,10 +955,24 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
           addr2 = GET_OFFSET();
           addr_ret = GET_OFFSET();
 
-          if (!cond)
+          if (!cond) {
+#if defined(BUILD_TARGET_X86_32)
+            if (addr_ret != addr1)
+              bh_memcpy_s(frame_lp + addr_ret, sizeof(int64),
+                          frame_lp + addr1, sizeof(int64));
+#else
             *(int64*)(frame_lp + addr_ret) = *(int64*)(frame_lp + addr1);
-          else
+#endif
+          }
+          else {
+#if defined(BUILD_TARGET_X86_32)
+            if (addr_ret != addr2)
+              bh_memcpy_s(frame_lp + addr_ret, sizeof(int64),
+                          frame_lp + addr2, sizeof(int64));
+#else
             *(int64*)(frame_lp + addr_ret) = *(int64*)(frame_lp + addr2);
+#endif
+          }
           HANDLE_OP_END ();
         }
 
@@ -1288,7 +1314,8 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
           frame_lp[addr_ret] = prev_page_count;
           /* update the memory instance ptr */
           memory = module->default_memory;
-          memory_data_size = num_bytes_per_page * memory->cur_page_count;
+          total_mem_size = num_bytes_per_page * memory->cur_page_count
+                           - heap_base_offset;
           global_data = memory->global_data;
         }
 
@@ -2061,13 +2088,23 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
       HANDLE_OP (EXT_OP_COPY_STACK_TOP):
         addr1 = GET_OFFSET();
         addr2 = GET_OFFSET();
+#if defined(BUILD_TARGET_X86_32)
+        bh_memcpy_s(frame_lp + addr2, sizeof(int32),
+                    frame_lp + addr1, sizeof(int32));
+#else
         frame_lp[addr2] = frame_lp[addr1];
+#endif
         HANDLE_OP_END ();
 
       HANDLE_OP (EXT_OP_COPY_STACK_TOP_I64):
         addr1 = GET_OFFSET();
         addr2 = GET_OFFSET();
+#if defined(BUILD_TARGET_X86_32)
+        bh_memcpy_s(frame_lp + addr2, sizeof(int64),
+                    frame_lp + addr1, sizeof(int64));
+#else
         *(float64*)(frame_lp + addr2) = *(float64*)(frame_lp + addr1);
+#endif
         HANDLE_OP_END ();
 
       HANDLE_OP (WASM_OP_SET_LOCAL):

+ 27 - 23
core/iwasm/interpreter/wasm_loader.c

@@ -2816,21 +2816,21 @@ wasm_loader_check_br(WASMLoaderContext *ctx, uint32 depth,
 
 #define GET_CONST_OFFSET(type, val) do {                                \
     if (!(wasm_loader_get_const_offset(loader_ctx, type,                \
-                                       val, 0, 0, &operand_offset,      \
+                                       &val, &operand_offset,           \
                                        error_buf, error_buf_size)))     \
         goto fail;                                                      \
   } while (0)
 
 #define GET_CONST_F32_OFFSET(type, fval) do {                           \
     if (!(wasm_loader_get_const_offset(loader_ctx, type,                \
-                                       0, fval, 0, &operand_offset,     \
+                                       &fval, &operand_offset,          \
                                        error_buf, error_buf_size)))     \
         goto fail;                                                      \
   } while (0)
 
 #define GET_CONST_F64_OFFSET(type, fval) do {                           \
     if (!(wasm_loader_get_const_offset(loader_ctx, type,                \
-                                       0, 0, fval, &operand_offset,     \
+                                       &fval, &operand_offset,          \
                                        error_buf, error_buf_size)))     \
         goto fail;                                                      \
   } while (0)
@@ -3110,9 +3110,11 @@ wasm_loader_push_frame_offset(WASMLoaderContext *ctx, uint8 type,
     }
 
     ctx->frame_offset++;
-    ctx->dynamic_offset++;
-    if (ctx->dynamic_offset > ctx->max_dynamic_offset)
-        ctx->max_dynamic_offset = ctx->dynamic_offset;
+    if (!disable_emit) {
+        ctx->dynamic_offset++;
+        if (ctx->dynamic_offset > ctx->max_dynamic_offset)
+            ctx->max_dynamic_offset = ctx->dynamic_offset;
+    }
     return true;
 }
 
@@ -3170,8 +3172,7 @@ wasm_loader_pop_frame_ref_offset(WASMLoaderContext *ctx, uint8 type,
 
 static bool
 wasm_loader_get_const_offset(WASMLoaderContext *ctx, uint8 type,
-                             int64 val_int, float32 val_f32,
-                             float64 val_f64, int16 *offset,
+                             void *value, int16 *offset,
                              char *error_buf, uint32 error_buf_size)
 {
     int16 operand_offset = 0;
@@ -3179,10 +3180,12 @@ wasm_loader_get_const_offset(WASMLoaderContext *ctx, uint8 type,
     for (c = (Const *)ctx->const_buf;
          (uint8*)c < ctx->const_buf + ctx->num_const * sizeof(Const); c ++) {
         if ((type == c->value_type)
-            && ((type == VALUE_TYPE_I64 && (int64)val_int == c->value.i64)
-            || (type == VALUE_TYPE_I32 && (int32)val_int == c->value.i32)
-            || (type == VALUE_TYPE_F64 && (float64)val_f64 == c->value.f64)
-            || (type == VALUE_TYPE_F32 && (float32)val_f32 == c->value.f32))) {
+            && ((type == VALUE_TYPE_I64 && *(int64*)value == c->value.i64)
+            || (type == VALUE_TYPE_I32 && *(int32*)value == c->value.i32)
+            || (type == VALUE_TYPE_F64
+                && (0 == memcmp(value, &(c->value.f64), sizeof(float64))))
+            || (type == VALUE_TYPE_F32
+                && (0 == memcmp(value, &(c->value.f32), sizeof(float32)))))) {
             operand_offset = c->slot_index;
             break;
         }
@@ -3203,23 +3206,23 @@ wasm_loader_get_const_offset(WASMLoaderContext *ctx, uint8 type,
         c->value_type = type;
         switch (type) {
         case VALUE_TYPE_F64:
-            c->value.f64 = (float64)val_f64;
+            bh_memcpy_s(&(c->value.f64), sizeof(WASMValue), value, sizeof(float64));
             ctx->const_cell_num += 2;
             /* The const buf will be reversed, we use the second cell */
             /* of the i64/f64 const so the finnal offset is corrent */
             operand_offset ++;
             break;
         case VALUE_TYPE_I64:
-            c->value.i64 = (int64)val_int;
+            c->value.i64 = *(int64*)value;
             ctx->const_cell_num += 2;
             operand_offset ++;
             break;
         case VALUE_TYPE_F32:
-            c->value.f32 = (float32)val_f32;
+            bh_memcpy_s(&(c->value.f32), sizeof(WASMValue), value, sizeof(float32));
             ctx->const_cell_num ++;
             break;
         case VALUE_TYPE_I32:
-            c->value.i32 = (int32)val_int;
+            c->value.i32 = *(int32*)value;
             ctx->const_cell_num ++;
             break;
         default:
@@ -3495,8 +3498,8 @@ re_scan:
     if (loader_ctx->code_compiled_size > 0) {
         if (!wasm_loader_ctx_reinit(loader_ctx)) {
             set_error_buf(error_buf, error_buf_size,
-                      "WASM loader prepare bytecode failed: "
-                      "allocate memory failed");
+                          "WASM loader prepare bytecode failed: "
+                          "allocate memory failed");
             goto fail;
         }
         p = func->code;
@@ -4005,7 +4008,7 @@ handle_next_reachable_block:
 #if WASM_ENABLE_FAST_INTERP != 0
                         if (loader_ctx->p_code_compiled) {
 #if WASM_ENABLE_ABS_LABEL_ADDR != 0
-                            *(void**)(loader_ctx->p_code_compiled - 10) =
+                            *(void**)(loader_ctx->p_code_compiled - 2 - sizeof(void*)) =
                                 handle_table[WASM_OP_SELECT_64];
 #else
                             *((int16*)loader_ctx->p_code_compiled - 2) = (int16)
@@ -4373,7 +4376,7 @@ handle_next_reachable_block:
 #if WASM_ENABLE_FAST_INTERP != 0
                 skip_label();
                 disable_emit = true;
-                f32 = *(float32 *)p_org;
+                bh_memcpy_s((uint8*)&f32, sizeof(float32), p_org, sizeof(float32));
                 GET_CONST_F32_OFFSET(VALUE_TYPE_F32, f32);
 #endif
                 PUSH_F32();
@@ -4385,7 +4388,7 @@ handle_next_reachable_block:
                 skip_label();
                 disable_emit = true;
                 /* Some MCU may require 8-byte align */
-                memcpy((uint8*)&f64, p_org, sizeof(float64));
+                bh_memcpy_s((uint8*)&f64, sizeof(float64), p_org, sizeof(float64));
                 GET_CONST_F64_OFFSET(VALUE_TYPE_F64, f64);
 #endif
                 PUSH_F64();
@@ -4687,10 +4690,11 @@ handle_next_reachable_block:
         if (c->value_type == VALUE_TYPE_F64
             || c->value_type == VALUE_TYPE_I64) {
             bh_memcpy_s(func_const, func_const_end - func_const,
-                        &c->value.f64, sizeof(int64));
+                        &(c->value.f64), sizeof(int64));
             func_const += sizeof(int64);
         } else {
-            *(uint32*)func_const = c->value.i32;
+            bh_memcpy_s(func_const, func_const_end - func_const,
+                        &(c->value.f32), sizeof(int32));
             func_const += sizeof(int32);
         }
     }

+ 92 - 118
core/iwasm/interpreter/wasm_runtime.c

@@ -51,7 +51,6 @@ memories_deinstantiate(WASMMemoryInstance **memories, uint32 count)
             if (memories[i]) {
                 if (memories[i]->heap_handle)
                     mem_allocator_destroy(memories[i]->heap_handle);
-                wasm_runtime_free(memories[i]->heap_data);
                 wasm_runtime_free(memories[i]);
             }
         wasm_runtime_free(memories);
@@ -67,6 +66,7 @@ memory_instantiate(uint32 num_bytes_per_page,
 {
     WASMMemoryInstance *memory;
     uint64 total_size = offsetof(WASMMemoryInstance, base_addr) +
+                        (uint64)heap_size +
                         num_bytes_per_page * (uint64)init_page_count +
                         global_data_size;
 
@@ -83,42 +83,28 @@ memory_instantiate(uint32 num_bytes_per_page,
     memory->cur_page_count = init_page_count;
     memory->max_page_count = max_page_count;
 
-    memory->memory_data = memory->base_addr;
-
+    memory->heap_data = memory->base_addr;
+    memory->memory_data = memory->heap_data + heap_size;
     memory->global_data = memory->memory_data +
                           num_bytes_per_page * memory->cur_page_count;
     memory->global_data_size = global_data_size;
-
     memory->end_addr = memory->global_data + global_data_size;
 
-    /* Allocate heap space */
-    if (!(memory->heap_data = wasm_runtime_malloc(heap_size))) {
-        set_error_buf(error_buf, error_buf_size,
-                      "Instantiate memory failed: allocate memory failed.");
-        goto fail1;
-    }
-    memory->heap_data_end = memory->heap_data + heap_size;
+    bh_assert(memory->end_addr - (uint8*)memory == (uint32)total_size);
 
     /* Initialize heap */
     if (!(memory->heap_handle = mem_allocator_create
                 (memory->heap_data, heap_size))) {
-        goto fail2;
+        wasm_runtime_free(memory);
+        return NULL;
     }
 
-#if WASM_ENABLE_MEMORY_GROW != 0
-    memory->heap_base_offset = DEFAULT_APP_HEAP_BASE_OFFSET;
+#if WASM_ENABLE_SPEC_TEST == 0
+    memory->heap_base_offset = -(int32)heap_size;
 #else
-    memory->heap_base_offset = memory->end_addr - memory->memory_data;
+    memory->heap_base_offset = 0;
 #endif
-
     return memory;
-
-fail2:
-    wasm_runtime_free(memory->heap_data);
-
-fail1:
-    wasm_runtime_free(memory);
-    return NULL;
 }
 
 /**
@@ -811,6 +797,10 @@ wasm_instantiate(WASMModule *module,
     /* Initialize the thread related data */
     if (stack_size == 0)
         stack_size = DEFAULT_WASM_STACK_SIZE;
+#if WASM_ENABLE_SPEC_TEST != 0
+    if (stack_size < 48 *1024)
+        stack_size = 48 * 1024;
+#endif
     module_inst->default_wasm_stack_size = stack_size;
 
     /* Execute __post_instantiate function */
@@ -923,13 +913,13 @@ wasm_module_malloc(WASMModuleInstance *module_inst, uint32 size,
 {
     WASMMemoryInstance *memory = module_inst->default_memory;
     uint8 *addr = mem_allocator_malloc(memory->heap_handle, size);
-    if (p_native_addr)
-        *p_native_addr = addr;
     if (!addr) {
         wasm_set_exception(module_inst, "out of memory");
         return 0;
     }
-    return memory->heap_base_offset + (int32)(addr - memory->heap_data);
+    if (p_native_addr)
+        *p_native_addr = addr;
+    return (int32)(addr - memory->memory_data);
 }
 
 void
@@ -937,8 +927,8 @@ wasm_module_free(WASMModuleInstance *module_inst, int32 ptr)
 {
     if (ptr) {
         WASMMemoryInstance *memory = module_inst->default_memory;
-        uint8 *addr = memory->heap_data + (ptr - memory->heap_base_offset);
-        if (memory->heap_data < addr && addr < memory->heap_data_end)
+        uint8 *addr = memory->memory_data + ptr;
+        if (memory->heap_data < addr && addr < memory->memory_data)
             mem_allocator_free(memory->heap_handle, addr);
     }
 }
@@ -961,31 +951,20 @@ bool
 wasm_validate_app_addr(WASMModuleInstance *module_inst,
                        int32 app_offset, uint32 size)
 {
-    WASMMemoryInstance *memory;
-    uint8 *addr;
+    WASMMemoryInstance *memory = module_inst->default_memory;
+    int32 memory_data_size =
+        (int32)(memory->num_bytes_per_page * memory->cur_page_count);
 
     /* integer overflow check */
-    if(app_offset + (int32)size < app_offset) {
+    if (app_offset + (int32)size < app_offset) {
         goto fail;
     }
 
-    memory = module_inst->default_memory;
-    if (0 <= app_offset
-        && app_offset < memory->heap_base_offset) {
-        addr = memory->memory_data + app_offset;
-        if (!(memory->base_addr <= addr && addr + size <= memory->end_addr))
-            goto fail;
-        return true;
-    }
-    else if (memory->heap_base_offset < app_offset
-             && app_offset < memory->heap_base_offset
-                             + (memory->heap_data_end - memory->heap_data)) {
-        addr = memory->heap_data + (app_offset - memory->heap_base_offset);
-        if (!(memory->heap_data <= addr && addr + size <= memory->heap_data_end))
-            goto fail;
-        return true;
+    if (app_offset <= memory->heap_base_offset
+        || app_offset + (int32)size > memory_data_size) {
+        goto fail;
     }
-
+    return true;
 fail:
     wasm_set_exception(module_inst, "out of bounds memory access");
     return false;
@@ -995,18 +974,20 @@ bool
 wasm_validate_native_addr(WASMModuleInstance *module_inst,
                           void *native_ptr, uint32 size)
 {
-    uint8 *addr = native_ptr;
+    uint8 *addr = (uint8*)native_ptr;
     WASMMemoryInstance *memory = module_inst->default_memory;
+    int32 memory_data_size =
+        (int32)(memory->num_bytes_per_page * memory->cur_page_count);
 
     if (addr + size < addr) {
         goto fail;
     }
 
-    if ((memory->base_addr <= addr && addr + size <= memory->end_addr)
-        || (memory->heap_data <= addr && addr + size <= memory->heap_data_end)
-       )
-        return true;
-
+    if (addr <= memory->heap_data
+        || addr + size > memory->memory_data + memory_data_size) {
+        goto fail;
+    }
+    return true;
 fail:
     wasm_set_exception(module_inst, "out of bounds memory access");
     return false;
@@ -1017,14 +998,13 @@ wasm_addr_app_to_native(WASMModuleInstance *module_inst,
                         int32 app_offset)
 {
     WASMMemoryInstance *memory = module_inst->default_memory;
-    if (0 <= app_offset && app_offset < memory->heap_base_offset)
+    int32 memory_data_size =
+        (int32)(memory->num_bytes_per_page * memory->cur_page_count);
+
+    if (memory->heap_base_offset < app_offset
+        && app_offset < memory_data_size)
         return memory->memory_data + app_offset;
-    else if (memory->heap_base_offset < app_offset
-             && app_offset < memory->heap_base_offset
-                             + (memory->heap_data_end - memory->heap_data))
-        return memory->heap_data + (app_offset - memory->heap_base_offset);
-    else
-        return NULL;
+    return NULL;
 }
 
 int32
@@ -1032,15 +1012,14 @@ wasm_addr_native_to_app(WASMModuleInstance *module_inst,
                         void *native_ptr)
 {
     WASMMemoryInstance *memory = module_inst->default_memory;
-    if (memory->base_addr <= (uint8*)native_ptr
-        && (uint8*)native_ptr < memory->end_addr)
-        return (int32)((uint8*)native_ptr - memory->memory_data);
-    else if (memory->heap_data <= (uint8*)native_ptr
-             && (uint8*)native_ptr < memory->heap_data_end)
-        return memory->heap_base_offset
-               + (int32)((uint8*)native_ptr - memory->heap_data);
-    else
-        return 0;
+    uint8 *addr = (uint8*)native_ptr;
+    int32 memory_data_size =
+        (int32)(memory->num_bytes_per_page * memory->cur_page_count);
+
+    if (memory->heap_data < addr
+        && addr < memory->memory_data + memory_data_size)
+        return (int32)(addr - memory->memory_data);
+    return 0;
 }
 
 bool
@@ -1049,28 +1028,19 @@ wasm_get_app_addr_range(WASMModuleInstance *module_inst,
                         int32 *p_app_start_offset,
                         int32 *p_app_end_offset)
 {
-    int32 app_start_offset, app_end_offset;
     WASMMemoryInstance *memory = module_inst->default_memory;
-
-    if (0 <= app_offset && app_offset < memory->heap_base_offset) {
-        app_start_offset = 0;
-        app_end_offset = (int32)(memory->num_bytes_per_page * memory->cur_page_count);
-    }
-    else if (memory->heap_base_offset < app_offset
-             && app_offset < memory->heap_base_offset
-                             + (memory->heap_data_end - memory->heap_data)) {
-        app_start_offset = memory->heap_base_offset;
-        app_end_offset = memory->heap_base_offset
-                         + (int32)(memory->heap_data_end - memory->heap_data);
+    int32 memory_data_size =
+        (int32)(memory->num_bytes_per_page * memory->cur_page_count);
+
+    if (memory->heap_base_offset < app_offset
+        && app_offset < memory_data_size) {
+        if (p_app_start_offset)
+            *p_app_start_offset = memory->heap_base_offset;
+        if (p_app_end_offset)
+            *p_app_end_offset = memory_data_size;
+        return true;
     }
-    else
-        return false;
-
-    if (p_app_start_offset)
-        *p_app_start_offset = app_start_offset;
-    if (p_app_end_offset)
-        *p_app_end_offset = app_end_offset;
-    return true;
+    return false;
 }
 
 bool
@@ -1079,42 +1049,36 @@ wasm_get_native_addr_range(WASMModuleInstance *module_inst,
                            uint8 **p_native_start_addr,
                            uint8 **p_native_end_addr)
 {
-    uint8 *native_start_addr, *native_end_addr;
     WASMMemoryInstance *memory = module_inst->default_memory;
-
-    if (memory->base_addr <= (uint8*)native_ptr
-        && (uint8*)native_ptr < memory->end_addr) {
-        native_start_addr = memory->memory_data;
-        native_end_addr = memory->memory_data
-                          + memory->num_bytes_per_page * memory->cur_page_count;
-    }
-    else if (memory->heap_data <= (uint8*)native_ptr
-             && (uint8*)native_ptr < memory->heap_data_end) {
-        native_start_addr = memory->heap_data;
-        native_end_addr = memory->heap_data_end;
+    uint8 *addr = (uint8*)native_ptr;
+    int32 memory_data_size =
+        (int32)(memory->num_bytes_per_page * memory->cur_page_count);
+
+    if (memory->heap_data < addr
+        && addr < memory->memory_data + memory_data_size) {
+        if (p_native_start_addr)
+            *p_native_start_addr = memory->heap_data;
+        if (p_native_end_addr)
+            *p_native_end_addr = memory->memory_data + memory_data_size;
+        return true;
     }
-    else
-        return false;
-
-    if (p_native_start_addr)
-        *p_native_start_addr = native_start_addr;
-    if (p_native_end_addr)
-        *p_native_end_addr = native_end_addr;
-    return true;
+    return false;
 }
 
 bool
 wasm_enlarge_memory(WASMModuleInstance *module, uint32 inc_page_count)
 {
-#if WASM_ENABLE_MEMORY_GROW != 0
     WASMMemoryInstance *memory = module->default_memory, *new_memory;
+    uint32 heap_size = memory->memory_data - memory->heap_data;
     uint32 old_page_count = memory->cur_page_count;
     uint32 total_size_old = memory->end_addr - (uint8*)memory;
     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;
+    uint64 total_size = offsetof(WASMMemoryInstance, base_addr)
+                        + (uint64)heap_size
+                        + memory->num_bytes_per_page * (uint64)total_page_count
+                        + memory->global_data_size;
     uint8 *global_data_old;
+    void *heap_handle_old = memory->heap_handle;
 
     if (inc_page_count <= 0)
         /* No need to enlarge memory */
@@ -1131,8 +1095,13 @@ wasm_enlarge_memory(WASMModuleInstance *module, uint32 inc_page_count)
         return false;
     }
 
+    /* Destroy heap's lock firstly, if its memory is re-allocated,
+       we cannot access its lock again. */
+    mem_allocator_destroy_lock(memory->heap_handle);
     if (!(new_memory = wasm_runtime_realloc(memory, (uint32)total_size))) {
         if (!(new_memory = wasm_runtime_malloc((uint32)total_size))) {
+            /* Restore heap's lock if memory re-alloc failed */
+            mem_allocator_reinit_lock(memory->heap_handle);
             wasm_set_exception(module, "fail to enlarge memory.");
             return false;
         }
@@ -1144,8 +1113,17 @@ wasm_enlarge_memory(WASMModuleInstance *module, uint32 inc_page_count)
     memset((uint8*)new_memory + total_size_old,
            0, (uint32)total_size - total_size_old);
 
+    new_memory->heap_handle = (uint8*)heap_handle_old +
+                              ((uint8*)new_memory - (uint8*)memory);
+    if (mem_allocator_migrate(new_memory->heap_handle,
+                              heap_handle_old) != 0) {
+        wasm_set_exception(module, "fail to enlarge memory.");
+        return false;
+    }
+
     new_memory->cur_page_count = total_page_count;
-    new_memory->memory_data = new_memory->base_addr;
+    new_memory->heap_data = new_memory->base_addr;
+    new_memory->memory_data = new_memory->base_addr + heap_size;
     new_memory->global_data = new_memory->memory_data +
                               new_memory->num_bytes_per_page * total_page_count;
     new_memory->end_addr = new_memory->global_data + new_memory->global_data_size;
@@ -1160,10 +1138,6 @@ wasm_enlarge_memory(WASMModuleInstance *module, uint32 inc_page_count)
 
     module->memories[0] = module->default_memory = new_memory;
     return true;
-#else /* else of WASM_ENABLE_MEMORY_GROW */
-    wasm_set_exception(module, "unsupported operation: enlarge memory.");
-    return false;
-#endif /* end of WASM_ENABLE_MEMORY_GROW */
 }
 
 

+ 6 - 8
core/iwasm/interpreter/wasm_runtime.h

@@ -23,17 +23,16 @@ typedef struct WASMMemoryInstance {
     /* Maximum page count */
     uint32 max_page_count;
 
+    /* Heap base offset of wasm app */
+    int32 heap_base_offset;
     /* Heap data base address */
     uint8 *heap_data;
-    /* Heap data end address */
-    uint8 *heap_data_end;
     /* The heap created */
     void *heap_handle;
-    /* Heap base offset of wasm app */
-    int32 heap_base_offset;
 
     /* Memory data */
     uint8 *memory_data;
+
     /* Global data of global instances */
     uint8 *global_data;
     uint32 global_data_size;
@@ -42,12 +41,11 @@ typedef struct WASMMemoryInstance {
     uint8 *end_addr;
 
     /* Base address, the layout is:
-       thunk_argv data + thunk arg offsets +
-       memory data + global data
+       heap_data + memory data + global data
        memory data init size is: num_bytes_per_page * cur_page_count
        global data size is calculated in module instantiating
-       Note: when memory is re-allocated, the thunk argv data, thunk
-             argv offsets and memory data must be copied to new memory also.
+       Note: when memory is re-allocated, the heap data and memory data
+             must be copied to new memory also.
      */
     uint8 base_addr[1];
 } WASMMemoryInstance;

+ 128 - 54
core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.c

@@ -46,26 +46,54 @@ typedef struct iovec_app {
 } iovec_app_t;
 
 typedef struct WASIContext {
-    void *curfds;
-    void *prestats;
-    void *argv_environ;
+    int32 curfds_offset;
+    int32 prestats_offset;
+    int32 argv_environ_offset;
 } *wasi_ctx_t;
 
 wasi_ctx_t
 wasm_runtime_get_wasi_ctx(wasm_module_inst_t module_inst);
 
+static struct fd_table *
+wasi_ctx_get_curfds(wasm_module_inst_t module_inst,
+                    wasi_ctx_t wasi_ctx)
+{
+    return (struct fd_table *)
+        wasm_runtime_addr_app_to_native(module_inst,
+                                        wasi_ctx->curfds_offset);
+}
+
+static struct argv_environ_values *
+wasi_ctx_get_argv_environ(wasm_module_inst_t module_inst,
+                          wasi_ctx_t wasi_ctx)
+{
+    return (struct argv_environ_values *)
+        wasm_runtime_addr_app_to_native(module_inst,
+                                        wasi_ctx->argv_environ_offset);
+}
+
+static struct fd_prestats *
+wasi_ctx_get_prestats(wasm_module_inst_t module_inst,
+                      wasi_ctx_t wasi_ctx)
+{
+    return (struct fd_prestats *)
+        wasm_runtime_addr_app_to_native(module_inst,
+                                        wasi_ctx->prestats_offset);
+}
+
 static wasi_errno_t
 wasi_args_get(wasm_exec_env_t exec_env, int32 *argv_offsets, char *argv_buf)
 {
     wasm_module_inst_t module_inst = get_module_inst(exec_env);
     wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+    struct argv_environ_values *argv_environ =
+                wasi_ctx_get_argv_environ(module_inst, wasi_ctx);
     size_t argc, argv_buf_size, i;
     char **argv;
     uint64 total_size;
     wasi_errno_t err;
 
-    err = wasmtime_ssp_args_sizes_get(wasi_ctx->argv_environ,
-                                      &argc, &argv_buf_size);
+    err = wasmtime_ssp_args_sizes_get(argv_environ, &argc, &argv_buf_size);
     if (err)
         return err;
 
@@ -81,7 +109,7 @@ wasi_args_get(wasm_exec_env_t exec_env, int32 *argv_offsets, char *argv_buf)
         || !(argv = wasm_runtime_malloc((uint32)total_size)))
         return (wasi_errno_t)-1;
 
-    err = wasmtime_ssp_args_get(wasi_ctx->argv_environ, argv, argv_buf);
+    err = wasmtime_ssp_args_get(argv_environ, argv, argv_buf);
     if (err) {
         wasm_runtime_free(argv);
         return err;
@@ -101,6 +129,7 @@ wasi_args_sizes_get(wasm_exec_env_t exec_env,
 {
     wasm_module_inst_t module_inst = get_module_inst(exec_env);
     wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+    struct argv_environ_values *argv_environ;
     size_t argc, argv_buf_size;
     wasi_errno_t err;
 
@@ -108,7 +137,11 @@ wasi_args_sizes_get(wasm_exec_env_t exec_env,
         || !validate_native_addr(argv_buf_size_app, sizeof(uint32)))
         return (wasi_errno_t)-1;
 
-    err = wasmtime_ssp_args_sizes_get(wasi_ctx->argv_environ,
+    argv_environ = (struct argv_environ_values *)
+        wasm_runtime_addr_app_to_native(module_inst,
+                                        wasi_ctx->argv_environ_offset);
+
+    err = wasmtime_ssp_args_sizes_get(argv_environ,
                                       &argc, &argv_buf_size);
     if (err)
         return err;
@@ -151,12 +184,14 @@ wasi_environ_get(wasm_exec_env_t exec_env,
 {
     wasm_module_inst_t module_inst = get_module_inst(exec_env);
     wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+    struct argv_environ_values *argv_environ =
+                wasi_ctx_get_argv_environ(module_inst, wasi_ctx);
     size_t environ_count, environ_buf_size, i;
     uint64 total_size;
     char **environs;
     wasi_errno_t err;
 
-    err = wasmtime_ssp_environ_sizes_get(wasi_ctx->argv_environ,
+    err = wasmtime_ssp_environ_sizes_get(argv_environ,
                                          &environ_count, &environ_buf_size);
     if (err)
         return err;
@@ -174,7 +209,7 @@ wasi_environ_get(wasm_exec_env_t exec_env,
         || !(environs = wasm_runtime_malloc((uint32)total_size)))
         return (wasi_errno_t)-1;
 
-    err = wasmtime_ssp_environ_get(wasi_ctx->argv_environ, environs, environ_buf);
+    err = wasmtime_ssp_environ_get(argv_environ, environs, environ_buf);
     if (err) {
         wasm_runtime_free(environs);
         return err;
@@ -194,6 +229,8 @@ wasi_environ_sizes_get(wasm_exec_env_t exec_env,
 {
     wasm_module_inst_t module_inst = get_module_inst(exec_env);
     wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+    struct argv_environ_values *argv_environ =
+                wasi_ctx_get_argv_environ(module_inst, wasi_ctx);
     size_t environ_count, environ_buf_size;
     wasi_errno_t err;
 
@@ -201,7 +238,7 @@ wasi_environ_sizes_get(wasm_exec_env_t exec_env,
         || !validate_native_addr(environ_buf_size_app, sizeof(uint32)))
         return (wasi_errno_t)-1;
 
-    err = wasmtime_ssp_environ_sizes_get(wasi_ctx->argv_environ,
+    err = wasmtime_ssp_environ_sizes_get(argv_environ,
                                          &environ_count, &environ_buf_size);
     if (err)
         return err;
@@ -218,13 +255,14 @@ wasi_fd_prestat_get(wasm_exec_env_t exec_env,
 {
     wasm_module_inst_t module_inst = get_module_inst(exec_env);
     wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+    struct fd_prestats *prestats = wasi_ctx_get_prestats(module_inst, wasi_ctx);
     wasi_prestat_t prestat;
     wasi_errno_t err;
 
     if (!validate_native_addr(prestat_app, sizeof(wasi_prestat_app_t)))
         return (wasi_errno_t)-1;
 
-    err = wasmtime_ssp_fd_prestat_get(wasi_ctx->prestats, fd, &prestat);
+    err = wasmtime_ssp_fd_prestat_get(prestats, fd, &prestat);
     if (err)
         return err;
 
@@ -239,8 +277,9 @@ wasi_fd_prestat_dir_name(wasm_exec_env_t exec_env,
 {
     wasm_module_inst_t module_inst = get_module_inst(exec_env);
     wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+    struct fd_prestats *prestats = wasi_ctx_get_prestats(module_inst, wasi_ctx);
 
-    return wasmtime_ssp_fd_prestat_dir_name(wasi_ctx->prestats,
+    return wasmtime_ssp_fd_prestat_dir_name(prestats,
                                             fd, path, path_len);
 }
 
@@ -249,8 +288,10 @@ wasi_fd_close(wasm_exec_env_t exec_env, wasi_fd_t fd)
 {
     wasm_module_inst_t module_inst = get_module_inst(exec_env);
     wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+    struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+    struct fd_prestats *prestats = wasi_ctx_get_prestats(module_inst, wasi_ctx);
 
-    return wasmtime_ssp_fd_close(wasi_ctx->curfds, wasi_ctx->prestats, fd);
+    return wasmtime_ssp_fd_close(curfds, prestats, fd);
 }
 
 static wasi_errno_t
@@ -258,8 +299,9 @@ wasi_fd_datasync(wasm_exec_env_t exec_env, wasi_fd_t fd)
 {
     wasm_module_inst_t module_inst = get_module_inst(exec_env);
     wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+    struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
 
-    return wasmtime_ssp_fd_datasync(wasi_ctx->curfds, fd);
+    return wasmtime_ssp_fd_datasync(curfds, fd);
 }
 
 static wasi_errno_t
@@ -269,6 +311,7 @@ wasi_fd_pread(wasm_exec_env_t exec_env,
 {
     wasm_module_inst_t module_inst = get_module_inst(exec_env);
     wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+    struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
     wasi_iovec_t *iovec, *iovec_begin;
     uint64 total_size;
     size_t nread;
@@ -298,7 +341,7 @@ wasi_fd_pread(wasm_exec_env_t exec_env,
         iovec->buf_len = iovec_app->buf_len;
     }
 
-    err = wasmtime_ssp_fd_pread(wasi_ctx->curfds, fd, iovec_begin,
+    err = wasmtime_ssp_fd_pread(curfds, fd, iovec_begin,
                                 iovs_len, offset, &nread);
     if (err)
         goto fail;
@@ -320,6 +363,7 @@ wasi_fd_pwrite(wasm_exec_env_t exec_env,
 {
     wasm_module_inst_t module_inst = get_module_inst(exec_env);
     wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+    struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
     wasi_ciovec_t *ciovec, *ciovec_begin;
     uint64 total_size;
     size_t nwritten;
@@ -349,7 +393,7 @@ wasi_fd_pwrite(wasm_exec_env_t exec_env,
         ciovec->buf_len = iovec_app->buf_len;
     }
 
-    err = wasmtime_ssp_fd_pwrite(wasi_ctx->curfds, fd, ciovec_begin,
+    err = wasmtime_ssp_fd_pwrite(curfds, fd, ciovec_begin,
                                  iovs_len, offset, &nwritten);
     if (err)
         goto fail;
@@ -371,6 +415,7 @@ wasi_fd_read(wasm_exec_env_t exec_env,
 {
     wasm_module_inst_t module_inst = get_module_inst(exec_env);
     wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+    struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
     wasi_iovec_t *iovec, *iovec_begin;
     uint64 total_size;
     size_t nread;
@@ -400,7 +445,7 @@ wasi_fd_read(wasm_exec_env_t exec_env,
         iovec->buf_len = iovec_app->buf_len;
     }
 
-    err = wasmtime_ssp_fd_read(wasi_ctx->curfds, fd,
+    err = wasmtime_ssp_fd_read(curfds, fd,
                                iovec_begin, iovs_len, &nread);
     if (err)
         goto fail;
@@ -420,9 +465,10 @@ wasi_fd_renumber(wasm_exec_env_t exec_env, wasi_fd_t from, wasi_fd_t to)
 {
     wasm_module_inst_t module_inst = get_module_inst(exec_env);
     wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+    struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+    struct fd_prestats *prestats = wasi_ctx_get_prestats(module_inst, wasi_ctx);
 
-    return wasmtime_ssp_fd_renumber(wasi_ctx->curfds,
-                                    wasi_ctx->prestats, from, to);
+    return wasmtime_ssp_fd_renumber(curfds, prestats, from, to);
 }
 
 static wasi_errno_t
@@ -432,12 +478,12 @@ wasi_fd_seek(wasm_exec_env_t exec_env,
 {
     wasm_module_inst_t module_inst = get_module_inst(exec_env);
     wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+    struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
 
     if (!validate_native_addr(newoffset, sizeof(wasi_filesize_t)))
         return (wasi_errno_t)-1;
 
-    return wasmtime_ssp_fd_seek(wasi_ctx->curfds, fd,
-                                offset, whence, newoffset);
+    return wasmtime_ssp_fd_seek(curfds, fd, offset, whence, newoffset);
 }
 
 static wasi_errno_t
@@ -446,11 +492,12 @@ wasi_fd_tell(wasm_exec_env_t exec_env,
 {
     wasm_module_inst_t module_inst = get_module_inst(exec_env);
     wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+    struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
 
     if (!validate_native_addr(newoffset, sizeof(wasi_filesize_t)))
         return (wasi_errno_t)-1;
 
-    return wasmtime_ssp_fd_tell(wasi_ctx->curfds, fd, newoffset);
+    return wasmtime_ssp_fd_tell(curfds, fd, newoffset);
 }
 
 static wasi_errno_t
@@ -459,13 +506,14 @@ wasi_fd_fdstat_get(wasm_exec_env_t exec_env,
 {
     wasm_module_inst_t module_inst = get_module_inst(exec_env);
     wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+    struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
     wasi_fdstat_t fdstat;
     wasi_errno_t err;
 
     if (!validate_native_addr(fdstat_app, sizeof(wasi_fdstat_t)))
         return (wasi_errno_t)-1;
 
-    err = wasmtime_ssp_fd_fdstat_get(wasi_ctx->curfds, fd, &fdstat);
+    err = wasmtime_ssp_fd_fdstat_get(curfds, fd, &fdstat);
     if (err)
         return err;
 
@@ -479,8 +527,9 @@ wasi_fd_fdstat_set_flags(wasm_exec_env_t exec_env,
 {
     wasm_module_inst_t module_inst = get_module_inst(exec_env);
     wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+    struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
 
-    return wasmtime_ssp_fd_fdstat_set_flags(wasi_ctx->curfds, fd, flags);
+    return wasmtime_ssp_fd_fdstat_set_flags(curfds, fd, flags);
 }
 
 static wasi_errno_t
@@ -491,8 +540,9 @@ wasi_fd_fdstat_set_rights(wasm_exec_env_t exec_env,
 {
     wasm_module_inst_t module_inst = get_module_inst(exec_env);
     wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+    struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
 
-    return wasmtime_ssp_fd_fdstat_set_rights(wasi_ctx->curfds, fd,
+    return wasmtime_ssp_fd_fdstat_set_rights(curfds, fd,
                                              fs_rights_base, fs_rights_inheriting);
 }
 
@@ -501,8 +551,9 @@ wasi_fd_sync(wasm_exec_env_t exec_env, wasi_fd_t fd)
 {
     wasm_module_inst_t module_inst = get_module_inst(exec_env);
     wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+    struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
 
-    return wasmtime_ssp_fd_sync(wasi_ctx->curfds, fd);
+    return wasmtime_ssp_fd_sync(curfds, fd);
 }
 
 static wasi_errno_t
@@ -512,6 +563,7 @@ wasi_fd_write(wasm_exec_env_t exec_env, wasi_fd_t fd,
 {
     wasm_module_inst_t module_inst = get_module_inst(exec_env);
     wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+    struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
     wasi_ciovec_t *ciovec, *ciovec_begin;
     uint64 total_size;
     size_t nwritten;
@@ -541,7 +593,7 @@ wasi_fd_write(wasm_exec_env_t exec_env, wasi_fd_t fd,
         ciovec->buf_len = iovec_app->buf_len;
     }
 
-    err = wasmtime_ssp_fd_write(wasi_ctx->curfds, fd,
+    err = wasmtime_ssp_fd_write(curfds, fd,
                                 ciovec_begin, iovs_len, &nwritten);
     if (err)
         goto fail;
@@ -565,8 +617,9 @@ wasi_fd_advise(wasm_exec_env_t exec_env,
 {
     wasm_module_inst_t module_inst = get_module_inst(exec_env);
     wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+    struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
 
-    return wasmtime_ssp_fd_advise(wasi_ctx->curfds, fd, offset, len, advice);
+    return wasmtime_ssp_fd_advise(curfds, fd, offset, len, advice);
 }
 
 static wasi_errno_t
@@ -577,8 +630,9 @@ wasi_fd_allocate(wasm_exec_env_t exec_env,
 {
     wasm_module_inst_t module_inst = get_module_inst(exec_env);
     wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+    struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
 
-    return wasmtime_ssp_fd_allocate(wasi_ctx->curfds, fd, offset, len);
+    return wasmtime_ssp_fd_allocate(curfds, fd, offset, len);
 }
 
 static wasi_errno_t
@@ -587,8 +641,9 @@ wasi_path_create_directory(wasm_exec_env_t exec_env,
 {
     wasm_module_inst_t module_inst = get_module_inst(exec_env);
     wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+    struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
 
-    return wasmtime_ssp_path_create_directory(wasi_ctx->curfds, fd,
+    return wasmtime_ssp_path_create_directory(curfds, fd,
                                               path, path_len);
 }
 
@@ -602,8 +657,10 @@ wasi_path_link(wasm_exec_env_t exec_env,
 {
     wasm_module_inst_t module_inst = get_module_inst(exec_env);
     wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+    struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+    struct fd_prestats *prestats = wasi_ctx_get_prestats(module_inst, wasi_ctx);
 
-    return wasmtime_ssp_path_link(wasi_ctx->curfds, wasi_ctx->prestats,
+    return wasmtime_ssp_path_link(curfds, prestats,
                                   old_fd, old_flags, old_path, old_path_len,
                                   new_fd, new_path, new_path_len);
 }
@@ -621,20 +678,21 @@ wasi_path_open(wasm_exec_env_t exec_env,
 {
     wasm_module_inst_t module_inst = get_module_inst(exec_env);
     wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+    struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
     wasi_fd_t fd = -1; /* set fd_app -1 if path open failed */
     wasi_errno_t err;
 
     if (!validate_native_addr(fd_app, sizeof(wasi_fd_t)))
         return (wasi_errno_t)-1;
 
-    err = wasmtime_ssp_path_open(wasi_ctx->curfds,
-                                  dirfd, dirflags,
-                                  path, path_len,
-                                  oflags,
-                                  fs_rights_base,
-                                  fs_rights_inheriting,
-                                  fs_flags,
-                                  &fd);
+    err = wasmtime_ssp_path_open(curfds,
+                                 dirfd, dirflags,
+                                 path, path_len,
+                                 oflags,
+                                 fs_rights_base,
+                                 fs_rights_inheriting,
+                                 fs_flags,
+                                 &fd);
 
     *fd_app = fd;
     return err;
@@ -649,13 +707,14 @@ wasi_fd_readdir(wasm_exec_env_t exec_env,
 {
     wasm_module_inst_t module_inst = get_module_inst(exec_env);
     wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+    struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
     size_t bufused;
     wasi_errno_t err;
 
     if (!validate_native_addr(bufused_app, sizeof(uint32)))
         return (wasi_errno_t)-1;
 
-    err = wasmtime_ssp_fd_readdir(wasi_ctx->curfds, fd,
+    err = wasmtime_ssp_fd_readdir(curfds, fd,
                                   buf, buf_len, cookie, &bufused);
     if (err)
         return err;
@@ -673,13 +732,14 @@ wasi_path_readlink(wasm_exec_env_t exec_env,
 {
     wasm_module_inst_t module_inst = get_module_inst(exec_env);
     wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+    struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
     size_t bufused;
     wasi_errno_t err;
 
     if (!validate_native_addr(bufused_app, sizeof(uint32)))
         return (wasi_errno_t)-1;
 
-    err = wasmtime_ssp_path_readlink(wasi_ctx->curfds, fd,
+    err = wasmtime_ssp_path_readlink(curfds, fd,
                                      path, path_len,
                                      buf, buf_len, &bufused);
     if (err)
@@ -696,8 +756,9 @@ wasi_path_rename(wasm_exec_env_t exec_env,
 {
     wasm_module_inst_t module_inst = get_module_inst(exec_env);
     wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+    struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
 
-    return wasmtime_ssp_path_rename(wasi_ctx->curfds,
+    return wasmtime_ssp_path_rename(curfds,
                                     old_fd, old_path, old_path_len,
                                     new_fd, new_path, new_path_len);
 }
@@ -708,11 +769,12 @@ wasi_fd_filestat_get(wasm_exec_env_t exec_env,
 {
     wasm_module_inst_t module_inst = get_module_inst(exec_env);
     wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+    struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
 
     if (!validate_native_addr(filestat, sizeof(wasi_filestat_t)))
         return (wasi_errno_t)-1;
 
-    return wasmtime_ssp_fd_filestat_get(wasi_ctx->curfds, fd, filestat);
+    return wasmtime_ssp_fd_filestat_get(curfds, fd, filestat);
 }
 
 static wasi_errno_t
@@ -724,8 +786,9 @@ wasi_fd_filestat_set_times(wasm_exec_env_t exec_env,
 {
     wasm_module_inst_t module_inst = get_module_inst(exec_env);
     wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+    struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
 
-    return wasmtime_ssp_fd_filestat_set_times(wasi_ctx->curfds, fd,
+    return wasmtime_ssp_fd_filestat_set_times(curfds, fd,
                                               st_atim, st_mtim, fstflags);
 }
 
@@ -736,8 +799,9 @@ wasi_fd_filestat_set_size(wasm_exec_env_t exec_env,
 {
     wasm_module_inst_t module_inst = get_module_inst(exec_env);
     wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+    struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
 
-    return wasmtime_ssp_fd_filestat_set_size(wasi_ctx->curfds, fd, st_size);
+    return wasmtime_ssp_fd_filestat_set_size(curfds, fd, st_size);
 }
 
 static wasi_errno_t
@@ -749,11 +813,12 @@ wasi_path_filestat_get(wasm_exec_env_t exec_env,
 {
     wasm_module_inst_t module_inst = get_module_inst(exec_env);
     wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+    struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
 
     if (!validate_native_addr(filestat, sizeof(wasi_filestat_t)))
         return (wasi_errno_t)-1;
 
-    return wasmtime_ssp_path_filestat_get(wasi_ctx->curfds, fd,
+    return wasmtime_ssp_path_filestat_get(curfds, fd,
                                           flags, path, path_len, filestat);
 }
 
@@ -768,8 +833,9 @@ wasi_path_filestat_set_times(wasm_exec_env_t exec_env,
 {
     wasm_module_inst_t module_inst = get_module_inst(exec_env);
     wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+    struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
 
-    return wasmtime_ssp_path_filestat_set_times(wasi_ctx->curfds, fd,
+    return wasmtime_ssp_path_filestat_set_times(curfds, fd,
                                                 flags, path, path_len,
                                                 st_atim, st_mtim, fstflags);
 }
@@ -781,8 +847,10 @@ wasi_path_symlink(wasm_exec_env_t exec_env,
 {
     wasm_module_inst_t module_inst = get_module_inst(exec_env);
     wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+    struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+    struct fd_prestats *prestats = wasi_ctx_get_prestats(module_inst, wasi_ctx);
 
-    return wasmtime_ssp_path_symlink(wasi_ctx->curfds, wasi_ctx->prestats,
+    return wasmtime_ssp_path_symlink(curfds, prestats,
                                      old_path, old_path_len, fd,
                                      new_path, new_path_len);
 }
@@ -793,8 +861,9 @@ wasi_path_unlink_file(wasm_exec_env_t exec_env,
 {
     wasm_module_inst_t module_inst = get_module_inst(exec_env);
     wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+    struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
 
-    return wasmtime_ssp_path_unlink_file(wasi_ctx->curfds, fd, path, path_len);
+    return wasmtime_ssp_path_unlink_file(curfds, fd, path, path_len);
 }
 
 static wasi_errno_t
@@ -803,8 +872,9 @@ wasi_path_remove_directory(wasm_exec_env_t exec_env,
 {
     wasm_module_inst_t module_inst = get_module_inst(exec_env);
     wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+    struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
 
-    return wasmtime_ssp_path_remove_directory(wasi_ctx->curfds, fd, path, path_len);
+    return wasmtime_ssp_path_remove_directory(curfds, fd, path, path_len);
 }
 
 static wasi_errno_t
@@ -814,6 +884,7 @@ wasi_poll_oneoff(wasm_exec_env_t exec_env,
 {
     wasm_module_inst_t module_inst = get_module_inst(exec_env);
     wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+    struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
     size_t nevents;
     wasi_errno_t err;
 
@@ -822,7 +893,7 @@ wasi_poll_oneoff(wasm_exec_env_t exec_env,
         || !validate_native_addr(nevents_app, sizeof(uint32)))
         return (wasi_errno_t)-1;
 
-    err = wasmtime_ssp_poll_oneoff(wasi_ctx->curfds, in, out,
+    err = wasmtime_ssp_poll_oneoff(curfds, in, out,
                                    nsubscriptions, &nevents);
     if (err)
         return err;
@@ -864,6 +935,7 @@ wasi_sock_recv(wasm_exec_env_t exec_env,
 {
     wasm_module_inst_t module_inst = get_module_inst(exec_env);
     wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+    struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
     wasi_iovec_t *iovec, *iovec_begin;
     uint64 total_size;
     size_t ro_datalen;
@@ -894,7 +966,7 @@ wasi_sock_recv(wasm_exec_env_t exec_env,
         iovec->buf_len = ri_data->buf_len;
     }
 
-    err = wasmtime_ssp_sock_recv(wasi_ctx->curfds, sock,
+    err = wasmtime_ssp_sock_recv(curfds, sock,
                                  iovec_begin, ri_data_len,
                                  ri_flags, &ro_datalen,
                                  ro_flags);
@@ -920,6 +992,7 @@ wasi_sock_send(wasm_exec_env_t exec_env,
 {
     wasm_module_inst_t module_inst = get_module_inst(exec_env);
     wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+    struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
     wasi_ciovec_t *ciovec, *ciovec_begin;
     uint64 total_size;
     size_t so_datalen;
@@ -949,7 +1022,7 @@ wasi_sock_send(wasm_exec_env_t exec_env,
         ciovec->buf_len = si_data->buf_len;
     }
 
-    err = wasmtime_ssp_sock_send(wasi_ctx->curfds, sock,
+    err = wasmtime_ssp_sock_send(curfds, sock,
                                  ciovec_begin, si_data_len,
                                  si_flags, &so_datalen);
     if (err)
@@ -971,8 +1044,9 @@ wasi_sock_shutdown(wasm_exec_env_t exec_env,
 {
     wasm_module_inst_t module_inst = get_module_inst(exec_env);
     wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+    struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
 
-    return wasmtime_ssp_sock_shutdown(wasi_ctx->curfds, sock, how);
+    return wasmtime_ssp_sock_shutdown(curfds, sock, how);
 }
 
 static wasi_errno_t

+ 29 - 2
core/shared/mem-alloc/ems/ems_alloc.c

@@ -404,10 +404,11 @@ gc_realloc_vo_internal(void *vheap, void *ptr, gc_size_t size,
 #endif
 {
     gc_heap_t* heap = (gc_heap_t*) vheap;
-    hmu_t *hmu = NULL, *hmu_old = NULL;
+    hmu_t *hmu = NULL, *hmu_old = NULL, *hmu_next;
     gc_object_t ret = (gc_object_t) NULL, obj_old = (gc_object_t)ptr;
-    gc_size_t tot_size, tot_size_unaligned, tot_size_old = 0;
+    gc_size_t tot_size, tot_size_unaligned, tot_size_old = 0, tot_size_next;
     gc_size_t obj_size, obj_size_old;
+    hmu_type_t ut;
 
     /* hmu header + prefix + obj + suffix */
     tot_size_unaligned = HMU_SIZE + OBJ_PREFIX_SIZE + size + OBJ_SUFFIX_SIZE;
@@ -427,6 +428,32 @@ gc_realloc_vo_internal(void *vheap, void *ptr, gc_size_t size,
 
     os_mutex_lock(&heap->lock);
 
+    if (hmu_old) {
+        hmu_next = (hmu_t*)((char *)hmu_old + tot_size_old);
+        if (hmu_is_in_heap(heap, hmu_next)) {
+            ut = hmu_get_ut(hmu_next);
+            tot_size_next = hmu_get_size(hmu_next);
+            if (ut == HMU_FC
+                && tot_size <= tot_size_old + tot_size_next) {
+                /* current node and next node meets requirement */
+                unlink_hmu(heap, hmu_next);
+                hmu_set_size(hmu_old, tot_size);
+                memset((char*)hmu_old + tot_size_old, 0, tot_size - tot_size_old);
+#if BH_ENABLE_GC_VERIFY != 0
+                hmu_init_prefix_and_suffix(hmu_old, tot_size, file, line);
+#endif
+                if (tot_size < tot_size_old + tot_size_next) {
+                    hmu_next = (hmu_t*)((char*)hmu_old + tot_size);
+                    tot_size_next = tot_size_old + tot_size_next - tot_size;
+                    gci_add_fc(heap, hmu_next, tot_size_next);
+                }
+                os_mutex_unlock(&heap->lock);
+                return obj_old;
+            }
+        }
+    }
+
+
     hmu = alloc_hmu_ex(heap, tot_size);
     if (!hmu)
         goto finish;

+ 29 - 0
core/shared/mem-alloc/ems/ems_gc.h

@@ -72,6 +72,35 @@ gc_init_with_pool(char *buf, gc_size_t buf_size);
 int
 gc_destroy_with_pool(gc_handle_t handle);
 
+/**
+ * Migrate heap from one place to another place
+ *
+ * @param handle handle of the new heap
+ * @param handle_old handle of the old heap
+ *
+ * @return GC_SUCCESS if success, GC_ERROR otherwise
+ */
+int
+gc_migrate(gc_handle_t handle, gc_handle_t handle_old);
+
+/**
+ * Re-initialize lock of heap
+ *
+ * @param handle the heap handle
+ *
+ * @return GC_SUCCESS if success, GC_ERROR otherwise
+ */
+int
+gc_reinit_lock(gc_handle_t handle);
+
+/**
+ * Destroy lock of heap
+ *
+ * @param handle the heap handle
+ */
+void
+gc_destroy_lock(gc_handle_t handle);
+
 /**
  * Get Heap Stats
  *

+ 0 - 1
core/shared/mem-alloc/ems/ems_gc_internal.h

@@ -192,7 +192,6 @@ typedef struct gc_heap_struct {
 
     gc_uint8 *base_addr;
     gc_size_t current_size;
-    gc_size_t max_size;
 
     korp_mutex lock;
 

+ 62 - 2
core/shared/mem-alloc/ems/ems_kfc.c

@@ -35,7 +35,6 @@ gc_init_with_pool(char *buf, gc_size_t buf_size)
     }
 
     /* init all data structures*/
-    heap->max_size = heap_max_size;
     heap->current_size = heap_max_size;
     heap->base_addr = (gc_uint8*)base_addr;
     heap->heap_id = (gc_handle_t)heap;
@@ -82,11 +81,72 @@ gc_destroy_with_pool(gc_handle_t handle)
 {
     gc_heap_t *heap = (gc_heap_t *) handle;
     os_mutex_destroy(&heap->lock);
-    memset(heap->base_addr, 0, heap->max_size);
+    memset(heap->base_addr, 0, heap->current_size);
     memset(heap, 0, sizeof(gc_heap_t));
     return GC_SUCCESS;
 }
 
+static void
+adjust_ptr(uint8 **p_ptr, intptr_t offset)
+{
+    if (*p_ptr)
+        *p_ptr += offset;
+}
+
+int
+gc_migrate(gc_handle_t handle, gc_handle_t handle_old)
+{
+    gc_heap_t *heap = (gc_heap_t *) handle;
+    intptr_t offset = (uint8*)handle - (uint8*)handle_old;
+    hmu_t *cur = NULL, *end = NULL;
+    hmu_tree_node_t *tree_node;
+    gc_size_t size;
+
+    os_mutex_init(&heap->lock);
+
+    if (offset == 0)
+        return 0;
+
+    heap->heap_id = (gc_handle_t)heap;
+    heap->base_addr += offset;
+    adjust_ptr((uint8**)&heap->kfc_tree_root.left, offset);
+    adjust_ptr((uint8**)&heap->kfc_tree_root.right, offset);
+    adjust_ptr((uint8**)&heap->kfc_tree_root.parent, offset);
+
+    cur = (hmu_t*)heap->base_addr;
+    end = (hmu_t*)((char*)heap->base_addr + heap->current_size);
+
+    while (cur < end) {
+        size = hmu_get_size(cur);
+        bh_assert(size > 0);
+
+        if (!HMU_IS_FC_NORMAL(size)) {
+            tree_node = (hmu_tree_node_t *)cur;
+            adjust_ptr((uint8**)&tree_node->left, offset);
+            adjust_ptr((uint8**)&tree_node->right, offset);
+            adjust_ptr((uint8**)&tree_node->parent, offset);
+        }
+        cur = (hmu_t*)((char *)cur + size);
+    }
+
+    bh_assert(cur == end);
+    return 0;
+}
+
+int
+gc_reinit_lock(gc_handle_t handle)
+{
+    gc_heap_t *heap = (gc_heap_t *) handle;
+    return os_mutex_init(&heap->lock);
+}
+
+void
+gc_destroy_lock(gc_handle_t handle)
+{
+    gc_heap_t *heap = (gc_heap_t *) handle;
+    os_mutex_destroy(&heap->lock);
+}
+
 #if BH_ENABLE_GC_VERIFY != 0
 void
 gci_verify_heap(gc_heap_t *heap)

+ 42 - 0
core/shared/mem-alloc/mem_alloc.c

@@ -37,6 +37,26 @@ void mem_allocator_free(mem_allocator_t allocator, void *ptr)
         gc_free_vo((gc_handle_t) allocator, ptr);
 }
 
+int
+mem_allocator_migrate(mem_allocator_t allocator,
+                      mem_allocator_t allocator_old)
+{
+    return gc_migrate((gc_handle_t) allocator,
+                      (gc_handle_t) allocator_old);
+}
+
+int
+mem_allocator_reinit_lock(mem_allocator_t allocator)
+{
+    return gc_reinit_lock((gc_handle_t) allocator);
+}
+
+void
+mem_allocator_destroy_lock(mem_allocator_t allocator)
+{
+    gc_destroy_lock((gc_handle_t) allocator);
+}
+
 #else /* else of DEFAULT_MEM_ALLOCATOR */
 
 #include "tlsf/tlsf.h"
@@ -141,5 +161,27 @@ mem_allocator_free(mem_allocator_t allocator, void *ptr)
     }
 }
 
+int
+mem_allocator_migrate(mem_allocator_t allocator,
+                      mem_allocator_t allocator_old)
+{
+    return tlsf_migrate((mem_allocator_tlsf *) allocator,
+                        (mem_allocator_tlsf *) allocator_old);
+}
+
+int
+mem_allocator_init_lock(mem_allocator_t allocator)
+{
+    mem_allocator_tlsf *allocator_tlsf = (mem_allocator_tlsf *)allocator;
+    return os_mutex_init(&allocator_tlsf->lock);
+}
+
+void
+mem_allocator_destroy_lock(mem_allocator_t allocator)
+{
+    mem_allocator_tlsf *allocator_tlsf = (mem_allocator_tlsf *)allocator;
+    os_mutex_destroy(&allocator_tlsf->lock);
+}
+
 #endif /* end of DEFAULT_MEM_ALLOCATOR */
 

+ 10 - 0
core/shared/mem-alloc/mem_alloc.h

@@ -29,6 +29,16 @@ mem_allocator_realloc(mem_allocator_t allocator, void *ptr, uint32_t size);
 void
 mem_allocator_free(mem_allocator_t allocator, void *ptr);
 
+int
+mem_allocator_migrate(mem_allocator_t allocator,
+                      mem_allocator_t allocator_old);
+
+int
+mem_allocator_reinit_lock(mem_allocator_t allocator);
+
+void
+mem_allocator_destroy_lock(mem_allocator_t allocator);
+
 #ifdef __cplusplus
 }
 #endif

+ 1 - 1
doc/build_wasm_app.md

@@ -129,7 +129,7 @@ Run the test.wasm or test.aot with WAMR mini product build:
 You will get the following output:
 ```
 Hello world!
-buf ptr: 0x400002b0
+buf ptr: 0xffffc2c8
 buf: 1234
 ```
 If you would like to run the test app on Zephyr, we have embedded a test sample into its OS image. You will need to execute:

+ 1 - 1
product-mini/platforms/zephyr/simple/build_and_run.sh

@@ -345,7 +345,7 @@ static host_interface interface = { .send = uart_send, .destroy = uart_destroy }
 #endif
 
 #ifdef __x86_64__
-static char global_heap_buf[420 * 1024] = { 0 };
+static char global_heap_buf[400 * 1024] = { 0 };
 #else
 static char global_heap_buf[270 * 1024] = { 0 };
 #endif