Przeglądaj źródła

Update API comments, refine footprint of wasm loader (#256)

and fix issues of get native stack boundary
wenyongh 5 lat temu
rodzic
commit
a0bb761beb

+ 22 - 15
core/iwasm/include/wasm_export.h

@@ -179,7 +179,9 @@ package_type_t
 get_package_type(const uint8_t *buf, uint32_t size);
 get_package_type(const uint8_t *buf, uint32_t size);
 
 
 /**
 /**
- * Load a WASM module from a specified byte buffer.
+ * Load a WASM module from a specified byte buffer. The byte buffer can be
+ * WASM binary data when interpreter or JIT is enabled, or AOT binary data
+ * when AOT is enabled. If it is AOT binary data, it must be 4-byte aligned.
  *
  *
  * @param buf the byte buffer which contains the WASM binary data
  * @param buf the byte buffer which contains the WASM binary data
  * @param size the size of the buffer
  * @param size the size of the buffer
@@ -225,11 +227,13 @@ wasm_runtime_set_wasi_args(wasm_module_t module,
  * Instantiate a WASM module.
  * Instantiate a WASM module.
  *
  *
  * @param module the WASM module to instantiate
  * @param module the WASM module to instantiate
- * @param stack_size the default stack size of the module instance, a stack
- *        will be created when function wasm_runtime_call_wasm() is called
- *        to run WASM function and the exec_env argument passed to
- *        wasm_runtime_call_wasm() is NULL. That means this parameter is
- *        ignored if exec_env is not NULL.
+ * @param stack_size the default stack size of the module instance when the
+ *        exec env's operation stack isn't created by user, e.g. API
+ *        wasm_application_execute_main() and wasm_application_execute_func()
+ *        create the operation stack internally with the stack size specified
+ *        here. And API wasm_runtime_create_exec_env() creates the operation
+ *        stack with stack size specified by its parameter, the stack size
+ *        specified here is ignored.
  * @param heap_size the default heap size of the module instance, a heap will
  * @param heap_size the default heap size of the module instance, a heap will
  *        be created besides the app memory space. Both wasm app and native
  *        be created besides the app memory space. Both wasm app and native
  *        function can allocate memory from the heap. If heap_size is 0, the
  *        function can allocate memory from the heap. If heap_size is 0, the
@@ -286,7 +290,7 @@ wasm_runtime_create_exec_env(wasm_module_inst_t module_inst,
 /**
 /**
  * Destroy the execution environment.
  * Destroy the execution environment.
  *
  *
- * @param env the execution environment to destroy
+ * @param exec_env the execution environment to destroy
  */
  */
 void
 void
 wasm_runtime_destroy_exec_env(wasm_exec_env_t exec_env);
 wasm_runtime_destroy_exec_env(wasm_exec_env_t exec_env);
@@ -305,17 +309,18 @@ wasm_runtime_get_module_inst(wasm_exec_env_t exec_env);
  * Call the given WASM function of a WASM module instance with
  * Call the given WASM function of a WASM module instance with
  * arguments (bytecode and AoT).
  * arguments (bytecode and AoT).
  *
  *
- * @param exec_env the execution environment to call the function
+ * @param exec_env the execution environment to call the function,
  *   which must be created from wasm_create_exec_env()
  *   which must be created from wasm_create_exec_env()
- * @param function the function to be called
+ * @param function the function to call
  * @param argc the number of arguments
  * @param argc the number of arguments
- * @param argv the arguments.  If the function method has return value,
+ * @param argv the arguments. If the function has return value,
  *   the first (or first two in case 64-bit return value) element of
  *   the first (or first two in case 64-bit return value) element of
  *   argv stores the return value of the called WASM function after this
  *   argv stores the return value of the called WASM function after this
  *   function returns.
  *   function returns.
  *
  *
  * @return true if success, false otherwise and exception will be thrown,
  * @return true if success, false otherwise and exception will be thrown,
- *   the caller can call wasm_runtime_get_exception to get exception info.
+ *   the caller can call wasm_runtime_get_exception to get the exception
+ *   info.
  */
  */
 bool
 bool
 wasm_runtime_call_wasm(wasm_exec_env_t exec_env,
 wasm_runtime_call_wasm(wasm_exec_env_t exec_env,
@@ -330,8 +335,9 @@ wasm_runtime_call_wasm(wasm_exec_env_t exec_env,
  * @param argc the number of arguments
  * @param argc the number of arguments
  * @param argv the arguments array
  * @param argv the arguments array
  *
  *
- * @return true if the main function is called, false otherwise and exception will be thrown,
- *   the caller can call wasm_runtime_get_exception to get exception info.
+ * @return true if the main function is called, false otherwise and exception
+ *   will be thrown, the caller can call wasm_runtime_get_exception to get 
+ *   the exception info.
  */
  */
 bool
 bool
 wasm_application_execute_main(wasm_module_inst_t module_inst,
 wasm_application_execute_main(wasm_module_inst_t module_inst,
@@ -346,8 +352,9 @@ wasm_application_execute_main(wasm_module_inst_t module_inst,
  * @param argc the number of arguments
  * @param argc the number of arguments
  * @param argv the arguments array
  * @param argv the arguments array
  *
  *
- * @return true if the specified function is called, false otherwise and exception will be thrown,
- *   the caller can call wasm_runtime_get_exception to get exception info.
+ * @return true if the specified function is called, false otherwise and
+ *   exception will be thrown, the caller can call wasm_runtime_get_exception
+ *   to get the exception info.
  */
  */
 bool
 bool
 wasm_application_execute_func(wasm_module_inst_t module_inst,
 wasm_application_execute_func(wasm_module_inst_t module_inst,

+ 225 - 235
core/iwasm/interpreter/wasm_loader.c

@@ -42,11 +42,11 @@ set_error_buf(char *error_buf, uint32 error_buf_size, const char *string)
 } while (0)
 } while (0)
 
 
 static bool
 static bool
-skip_leb(const uint8  *buf, const uint8 *buf_end,
-         uint32 *p_offset, uint32 maxbits,
+skip_leb(const uint8 **p_buf, const uint8 *buf_end, uint32 maxbits,
          char* error_buf, uint32 error_buf_size)
          char* error_buf, uint32 error_buf_size)
 {
 {
-    uint32 bcnt = 0;
+    const uint8 *buf = *p_buf;
+    uint32 offset = 0, bcnt = 0;
     uint64 byte;
     uint64 byte;
 
 
     while (true) {
     while (true) {
@@ -57,51 +57,46 @@ skip_leb(const uint8  *buf, const uint8 *buf_end,
             return false;
             return false;
         }
         }
 
 
-        CHECK_BUF(buf, buf_end, *p_offset + 1);
-        byte = buf[*p_offset];
-        *p_offset += 1;
+        CHECK_BUF(buf, buf_end, offset + 1);
+        byte = buf[offset];
+        offset += 1;
         bcnt += 1;
         bcnt += 1;
         if ((byte & 0x80) == 0) {
         if ((byte & 0x80) == 0) {
             break;
             break;
         }
         }
     }
     }
 
 
+    *p_buf += offset;
     return true;
     return true;
 }
 }
 
 
 #define skip_leb_int64(p, p_end) do {               \
 #define skip_leb_int64(p, p_end) do {               \
-  uint32 off = 0;                                   \
-  if (!skip_leb(p, p_end, &off, 64,                 \
+  if (!skip_leb(&p, p_end, 64,                      \
                 error_buf, error_buf_size))         \
                 error_buf, error_buf_size))         \
     return false;                                   \
     return false;                                   \
-  p += off;                                         \
 } while (0)
 } while (0)
 
 
 #define skip_leb_uint32(p, p_end) do {              \
 #define skip_leb_uint32(p, p_end) do {              \
-  uint32 off = 0;                                   \
-  if (!skip_leb(p, p_end, &off, 32,                 \
+  if (!skip_leb(&p, p_end, 32,                      \
                 error_buf, error_buf_size))         \
                 error_buf, error_buf_size))         \
     return false;                                   \
     return false;                                   \
-  p += off;                                         \
 } while (0)
 } while (0)
 
 
 #define skip_leb_int32(p, p_end) do {               \
 #define skip_leb_int32(p, p_end) do {               \
-  uint32 off = 0;                                   \
-  if (!skip_leb(p, p_end, &off, 32,                 \
+  if (!skip_leb(&p, p_end, 32,                      \
                 error_buf, error_buf_size))         \
                 error_buf, error_buf_size))         \
     return false;                                   \
     return false;                                   \
-  p += off;                                         \
 } while (0)
 } while (0)
 
 
 static bool
 static bool
-read_leb(const uint8 *buf, const uint8 *buf_end,
-         uint32 *p_offset, uint32 maxbits,
-         bool sign, uint64 *p_result,
+read_leb(uint8 **p_buf, const uint8 *buf_end,
+         uint32 maxbits, bool sign, uint64 *p_result,
          char* error_buf, uint32 error_buf_size)
          char* error_buf, uint32 error_buf_size)
 {
 {
+    const uint8 *buf = *p_buf;
     uint64 result = 0;
     uint64 result = 0;
     uint32 shift = 0;
     uint32 shift = 0;
-    uint32 bcnt = 0;
+    uint32 offset = 0, bcnt = 0;
     uint64 byte;
     uint64 byte;
 
 
     while (true) {
     while (true) {
@@ -112,9 +107,9 @@ read_leb(const uint8 *buf, const uint8 *buf_end,
             return false;
             return false;
         }
         }
 
 
-        CHECK_BUF(buf, buf_end, *p_offset + 1);
-        byte = buf[*p_offset];
-        *p_offset += 1;
+        CHECK_BUF(buf, buf_end, offset + 1);
+        byte = buf[offset];
+        offset += 1;
         result |= ((byte & 0x7f) << shift);
         result |= ((byte & 0x7f) << shift);
         shift += 7;
         shift += 7;
         bcnt += 1;
         bcnt += 1;
@@ -160,6 +155,7 @@ read_leb(const uint8 *buf, const uint8 *buf_end,
         }
         }
     }
     }
 
 
+    *p_buf += offset;
     *p_result = result;
     *p_result = result;
     return true;
     return true;
 
 
@@ -174,62 +170,26 @@ fail_integer_too_large:
 #define read_bool(p)   TEMPLATE_READ_VALUE(bool, p)
 #define read_bool(p)   TEMPLATE_READ_VALUE(bool, p)
 
 
 #define read_leb_int64(p, p_end, res) do {          \
 #define read_leb_int64(p, p_end, res) do {          \
-  if (p < p_end) {                                  \
-    uint8 _val = *p;                                \
-    if (!(_val & 0x80)) {                           \
-      res = (int64)_val;                            \
-      if (_val & 0x40)                              \
-        /* sign extend */                           \
-        res |= 0xFFFFFFFFFFFFFF80LL;                \
-      p++;                                          \
-      break;                                        \
-    }                                               \
-  }                                                 \
-  uint32 off = 0;                                   \
   uint64 res64;                                     \
   uint64 res64;                                     \
-  if (!read_leb(p, p_end, &off, 64, true, &res64,   \
+  if (!read_leb((uint8**)&p, p_end, 64, true, &res64,\
                 error_buf, error_buf_size))         \
                 error_buf, error_buf_size))         \
     return false;                                   \
     return false;                                   \
-  p += off;                                         \
   res = (int64)res64;                               \
   res = (int64)res64;                               \
 } while (0)
 } while (0)
 
 
 #define read_leb_uint32(p, p_end, res) do {         \
 #define read_leb_uint32(p, p_end, res) do {         \
-  if (p < p_end) {                                  \
-    uint8 _val = *p;                                \
-    if (!(_val & 0x80)) {                           \
-      res = _val;                                   \
-      p++;                                          \
-      break;                                        \
-    }                                               \
-  }                                                 \
-  uint32 off = 0;                                   \
   uint64 res64;                                     \
   uint64 res64;                                     \
-  if (!read_leb(p, p_end, &off, 32, false, &res64,  \
+  if (!read_leb((uint8**)&p, p_end, 32, false, &res64,\
                 error_buf, error_buf_size))         \
                 error_buf, error_buf_size))         \
     return false;                                   \
     return false;                                   \
-  p += off;                                         \
   res = (uint32)res64;                              \
   res = (uint32)res64;                              \
 } while (0)
 } while (0)
 
 
 #define read_leb_int32(p, p_end, res) do {          \
 #define read_leb_int32(p, p_end, res) do {          \
-  if (p < p_end) {                                  \
-    uint8 _val = *p;                                \
-    if (!(_val & 0x80)) {                           \
-      res = (int32)_val;                            \
-      if (_val & 0x40)                              \
-        /* sign extend */                           \
-        res |= 0xFFFFFF80;                          \
-      p++;                                          \
-      break;                                        \
-    }                                               \
-  }                                                 \
-  uint32 off = 0;                                   \
   uint64 res64;                                     \
   uint64 res64;                                     \
-  if (!read_leb(p, p_end, &off, 32, true, &res64,   \
+  if (!read_leb((uint8**)&p, p_end, 32, true, &res64,\
                 error_buf, error_buf_size))         \
                 error_buf, error_buf_size))         \
     return false;                                   \
     return false;                                   \
-  p += off;                                         \
   res = (int32)res64;                               \
   res = (int32)res64;                               \
 } while (0)
 } while (0)
 
 
@@ -2094,15 +2054,22 @@ wasm_loader_find_block_addr(BlockAddr *block_addr_cache,
 {
 {
     const uint8 *p = start_addr, *p_end = code_end_addr;
     const uint8 *p = start_addr, *p_end = code_end_addr;
     uint8 *else_addr = NULL;
     uint8 *else_addr = NULL;
-    uint32 block_nested_depth = 1, count, i;
+    uint32 block_nested_depth = 1, count, i, j, t;
     uint8 opcode, u8;
     uint8 opcode, u8;
-
     BlockAddr block_stack[16] = { 0 }, *block;
     BlockAddr block_stack[16] = { 0 }, *block;
-    uint32 j, t;
 
 
     i = ((uintptr_t)start_addr) % BLOCK_ADDR_CACHE_SIZE;
     i = ((uintptr_t)start_addr) % BLOCK_ADDR_CACHE_SIZE;
     block = block_addr_cache + BLOCK_ADDR_CONFLICT_SIZE * i;
     block = block_addr_cache + BLOCK_ADDR_CONFLICT_SIZE * i;
 
 
+    for (j = 0; j < BLOCK_ADDR_CONFLICT_SIZE; j++) {
+        if (block[j].start_addr == start_addr) {
+            /* Cache hit */
+            *p_else_addr = block[j].else_addr;
+            *p_end_addr = block[j].end_addr;
+            return true;
+        }
+    }
+
     /* Cache unhit */
     /* Cache unhit */
     block_stack[0].start_addr = start_addr;
     block_stack[0].start_addr = start_addr;
 
 
@@ -2761,6 +2728,20 @@ wasm_loader_pop_frame_ref(WASMLoaderContext *ctx, uint8 type,
     return true;
     return true;
 }
 }
 
 
+static bool
+wasm_loader_push_pop_frame_ref(WASMLoaderContext *ctx, uint8 pop_cnt,
+                               uint8 type_push, uint8 type_pop,
+                               char *error_buf, uint32 error_buf_size)
+{
+    for (int i = 0; i < pop_cnt; i++) {
+        if (!wasm_loader_pop_frame_ref(ctx, type_pop, error_buf, error_buf_size))
+            return false;
+    }
+    if (!wasm_loader_push_frame_ref(ctx, type_push, error_buf, error_buf_size))
+        return false;
+    return true;
+}
+
 static bool
 static bool
 wasm_loader_push_frame_csp(WASMLoaderContext *ctx, uint8 type,
 wasm_loader_push_frame_csp(WASMLoaderContext *ctx, uint8 type,
                            uint8 ret_type, uint8* start_addr,
                            uint8 ret_type, uint8* start_addr,
@@ -3253,6 +3234,24 @@ wasm_loader_pop_frame_offset(WASMLoaderContext *ctx, uint8 type,
     return true;
     return true;
 }
 }
 
 
+static bool
+wasm_loader_push_pop_frame_offset(WASMLoaderContext *ctx, uint8 pop_cnt,
+                                  uint8 type_push, uint8 type_pop,
+                                  bool disable_emit, int16 operand_offset,
+                                  char *error_buf, uint32 error_buf_size)
+{
+    for (int i = 0; i < pop_cnt; i++) {
+        if (!wasm_loader_pop_frame_offset(ctx, type_pop, error_buf, error_buf_size))
+            return false;
+    }
+    if (!wasm_loader_push_frame_offset(ctx, type_push,
+                                       disable_emit, operand_offset,
+                                       error_buf, error_buf_size))
+        return false;
+
+    return true;
+}
+
 static bool
 static bool
 wasm_loader_push_frame_ref_offset(WASMLoaderContext *ctx, uint8 type,
 wasm_loader_push_frame_ref_offset(WASMLoaderContext *ctx, uint8 type,
                                   bool disable_emit, int16 operand_offset,
                                   bool disable_emit, int16 operand_offset,
@@ -3279,6 +3278,22 @@ wasm_loader_pop_frame_ref_offset(WASMLoaderContext *ctx, uint8 type,
     return true;
     return true;
 }
 }
 
 
+static bool
+wasm_loader_push_pop_frame_ref_offset(WASMLoaderContext *ctx, uint8 pop_cnt,
+                                      uint8 type_push, uint8 type_pop,
+                                      bool disable_emit, int16 operand_offset,
+                                      char *error_buf, uint32 error_buf_size)
+{
+    if (!wasm_loader_push_pop_frame_ref(ctx, pop_cnt, type_push, type_pop,
+                                        error_buf, error_buf_size))
+        return false;
+    if (!wasm_loader_push_pop_frame_offset(ctx, pop_cnt, type_push, type_pop,
+                                           disable_emit, operand_offset,
+                                           error_buf, error_buf_size))
+        return false;
+
+    return true;
+}
 
 
 static bool
 static bool
 wasm_loader_get_const_offset(WASMLoaderContext *ctx, uint8 type,
 wasm_loader_get_const_offset(WASMLoaderContext *ctx, uint8 type,
@@ -3432,6 +3447,23 @@ fail:
         goto fail;                                                      \
         goto fail;                                                      \
   } while (0)
   } while (0)
 
 
+#define POP_AND_PUSH(type_pop, type_push) do {                                \
+    if (!(wasm_loader_push_pop_frame_ref_offset(loader_ctx, 1,                \
+                                                type_push, type_pop,          \
+                                                disable_emit, operand_offset, \
+                                                error_buf, error_buf_size)))  \
+        goto fail;                                                            \
+  } while (0)
+
+/* type of POPs should be the same */
+#define POP2_AND_PUSH(type_pop, type_push) do {                               \
+    if (!(wasm_loader_push_pop_frame_ref_offset(loader_ctx, 2,                \
+                                                type_push, type_pop,          \
+                                                disable_emit, operand_offset, \
+                                                error_buf, error_buf_size)))  \
+        goto fail;                                                            \
+  } while (0)
+
 #else /* WASM_ENABLE_FAST_INTERP */
 #else /* WASM_ENABLE_FAST_INTERP */
 
 
 #define PUSH_I32() do {                                             \
 #define PUSH_I32() do {                                             \
@@ -3482,8 +3514,85 @@ fail:
         goto fail;                                                  \
         goto fail;                                                  \
   } while (0)
   } while (0)
 
 
+#define POP_AND_PUSH(type_pop, type_push) do {                           \
+    if (!(wasm_loader_push_pop_frame_ref(loader_ctx, 1,                  \
+                                         type_push, type_pop,            \
+                                         error_buf, error_buf_size)))    \
+        goto fail;                                                       \
+  } while (0)
+
+/* type of POPs should be the same */
+#define POP2_AND_PUSH(type_pop, type_push) do {                          \
+    if (!(wasm_loader_push_pop_frame_ref(loader_ctx, 2,                  \
+                                         type_push, type_pop,            \
+                                         error_buf, error_buf_size)))    \
+        goto fail;                                                       \
+  } while (0)
 #endif /* WASM_ENABLE_FAST_INTERP */
 #endif /* WASM_ENABLE_FAST_INTERP */
 
 
+#if WASM_ENABLE_FAST_INTERP != 0
+
+static bool
+reserve_block_ret(WASMLoaderContext *loader_ctx, uint8 opcode, bool disable_emit,
+                  char *error_buf, uint32 error_buf_size)
+{
+    int16 operand_offset = 0;
+    uint8 block_depth = 0;
+    if (opcode == WASM_OP_ELSE)
+        block_depth = 1;
+    else
+        block_depth = 0;
+
+    if ((loader_ctx->frame_csp - block_depth)->return_type != VALUE_TYPE_VOID) {
+        uint8 return_cells;
+        if ((loader_ctx->frame_csp - block_depth)->return_type == VALUE_TYPE_I32
+            || (loader_ctx->frame_csp - block_depth)->return_type == VALUE_TYPE_F32)
+            return_cells = 1;
+        else
+            return_cells = 2;
+        if ((loader_ctx->frame_csp - block_depth)->dynamic_offset !=
+                *(loader_ctx->frame_offset - return_cells)) {
+
+            /* insert op_copy before else opcode */
+            if (opcode == WASM_OP_ELSE)
+                skip_label();
+
+            if (return_cells == 1)
+                emit_label(EXT_OP_COPY_STACK_TOP);
+            else
+                emit_label(EXT_OP_COPY_STACK_TOP_I64);
+            emit_operand(loader_ctx, *(loader_ctx->frame_offset - return_cells));
+            emit_operand(loader_ctx, (loader_ctx->frame_csp - block_depth)->dynamic_offset);
+
+            if (opcode == WASM_OP_ELSE) {
+                *(loader_ctx->frame_offset - return_cells) =
+                    (loader_ctx->frame_csp - block_depth)->dynamic_offset;
+            }
+            else {
+                loader_ctx->frame_offset -= return_cells;
+                loader_ctx->dynamic_offset = loader_ctx->frame_csp->dynamic_offset;
+                PUSH_OFFSET_TYPE((loader_ctx->frame_csp - block_depth)->return_type);
+                wasm_loader_emit_backspace(loader_ctx, sizeof(int16));
+            }
+            if (opcode == WASM_OP_ELSE)
+                emit_label(opcode);
+        }
+    }
+
+    return true;
+
+fail:
+    return false;
+}
+
+#endif /* WASM_ENABLE_FAST_INTERP */
+
+#define RESERVE_BLOCK_RET() do {                                    \
+     if (!reserve_block_ret(loader_ctx, opcode, disable_emit,       \
+                            error_buf, error_buf_size))             \
+        goto fail;                                                  \
+  } while (0)
+
 #define PUSH_TYPE(type) do {                                        \
 #define PUSH_TYPE(type) do {                                        \
     if (!(wasm_loader_push_frame_ref(loader_ctx, type,              \
     if (!(wasm_loader_push_frame_ref(loader_ctx, type,              \
                                      error_buf, error_buf_size)))   \
                                      error_buf, error_buf_size)))   \
@@ -3613,12 +3722,10 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func,
     uint8 *param_types, ret_type, *local_types, local_type, global_type;
     uint8 *param_types, ret_type, *local_types, local_type, global_type;
     uint16 *local_offsets, local_offset;
     uint16 *local_offsets, local_offset;
     uint32 count, i, local_idx, global_idx, u32, align, mem_offset;
     uint32 count, i, local_idx, global_idx, u32, align, mem_offset;
-    uint32 cache_index, item_index;
     int32 i32, i32_const = 0;
     int32 i32, i32_const = 0;
     int64 i64;
     int64 i64;
     uint8 opcode, u8, block_return_type;
     uint8 opcode, u8, block_return_type;
     bool return_value = false, is_i32_const = false;
     bool return_value = false, is_i32_const = false;
-    BlockAddr *cache_items;
     WASMLoaderContext *loader_ctx;
     WASMLoaderContext *loader_ctx;
     BranchBlock *frame_csp_tmp;
     BranchBlock *frame_csp_tmp;
 #if WASM_ENABLE_FAST_INTERP != 0
 #if WASM_ENABLE_FAST_INTERP != 0
@@ -3723,23 +3830,7 @@ re_scan:
                 if (!is_i32_const)
                 if (!is_i32_const)
                     (loader_ctx->frame_csp - 1)->is_block_reachable = true;
                     (loader_ctx->frame_csp - 1)->is_block_reachable = true;
                 else {
                 else {
-                    cache_index = ((uintptr_t)(loader_ctx->frame_csp - 1)->start_addr)
-                                   & (uintptr_t)(BLOCK_ADDR_CACHE_SIZE - 1);
-                    cache_items = block_addr_cache
-                                  + BLOCK_ADDR_CONFLICT_SIZE * cache_index;
-                    for (item_index = 0; item_index < BLOCK_ADDR_CONFLICT_SIZE;
-                         item_index++) {
-                        if (cache_items[item_index].start_addr ==
-                                (loader_ctx->frame_csp - 1)->start_addr) {
-                            (loader_ctx->frame_csp - 1)->else_addr =
-                                cache_items[item_index].else_addr;
-                            (loader_ctx->frame_csp - 1)->end_addr =
-                                cache_items[item_index].end_addr;
-                            break;
-                        }
-                    }
-                    if (item_index == BLOCK_ADDR_CONFLICT_SIZE
-                        && !wasm_loader_find_block_addr(block_addr_cache,
+                    if (!wasm_loader_find_block_addr(block_addr_cache,
                                         (loader_ctx->frame_csp - 1)->start_addr,
                                         (loader_ctx->frame_csp - 1)->start_addr,
                                         p_end,
                                         p_end,
                                         (loader_ctx->frame_csp - 1)->block_type,
                                         (loader_ctx->frame_csp - 1)->block_type,
@@ -3796,27 +3887,7 @@ re_scan:
                                             loader_ctx->stack_cell_num;
                                             loader_ctx->stack_cell_num;
 #if WASM_ENABLE_FAST_INTERP != 0
 #if WASM_ENABLE_FAST_INTERP != 0
                 /* if the result of if branch is in local or const area, add a copy op */
                 /* if the result of if branch is in local or const area, add a copy op */
-                if ((loader_ctx->frame_csp - 1)->return_type != VALUE_TYPE_VOID) {
-                    uint8 return_cells;
-                    if ((loader_ctx->frame_csp - 1)->return_type == VALUE_TYPE_I32
-                        || (loader_ctx->frame_csp - 1)->return_type == VALUE_TYPE_F32)
-                        return_cells = 1;
-                    else
-                        return_cells = 2;
-                    if ((loader_ctx->frame_csp - 1)->dynamic_offset !=
-                            *(loader_ctx->frame_offset - return_cells)) {
-                        skip_label();
-                        if (return_cells == 1)
-                            emit_label(EXT_OP_COPY_STACK_TOP);
-                        else
-                            emit_label(EXT_OP_COPY_STACK_TOP_I64);
-                        emit_operand(loader_ctx, *(loader_ctx->frame_offset - return_cells));
-                        emit_operand(loader_ctx, (loader_ctx->frame_csp - 1)->dynamic_offset);
-                        *(loader_ctx->frame_offset - return_cells) =
-                            (loader_ctx->frame_csp - 1)->dynamic_offset;
-                        emit_label(opcode);
-                    }
-                }
+                RESERVE_BLOCK_RET();
                 loader_ctx->frame_offset = loader_ctx->frame_offset_bottom +
                 loader_ctx->frame_offset = loader_ctx->frame_offset_bottom +
                                                 loader_ctx->stack_cell_num;
                                                 loader_ctx->stack_cell_num;
                 emit_empty_label_addr_and_frame_ip(PATCH_END);
                 emit_empty_label_addr_and_frame_ip(PATCH_END);
@@ -3830,29 +3901,8 @@ re_scan:
 
 
 #if WASM_ENABLE_FAST_INTERP != 0
 #if WASM_ENABLE_FAST_INTERP != 0
                 skip_label();
                 skip_label();
-                // copy the result to the block return address
-                if (loader_ctx->frame_csp->return_type != VALUE_TYPE_VOID) {
-                    uint8 return_cells;
-                    if (loader_ctx->frame_csp->return_type == VALUE_TYPE_I32
-                        || loader_ctx->frame_csp->return_type == VALUE_TYPE_F32)
-                        return_cells = 1;
-                    else
-                        return_cells = 2;
-                    if (loader_ctx->frame_csp->dynamic_offset !=
-                            *(loader_ctx->frame_offset - return_cells)) {
-                        if (return_cells == 1)
-                            emit_label(EXT_OP_COPY_STACK_TOP);
-                        else
-                            emit_label(EXT_OP_COPY_STACK_TOP_I64);
-                        emit_operand(loader_ctx, *(loader_ctx->frame_offset - return_cells));
-                        emit_operand(loader_ctx, loader_ctx->frame_csp->dynamic_offset);
-                    }
-                    // the frame_offset stack top should be the return address of the block
-                    loader_ctx->frame_offset -= return_cells;
-                    loader_ctx->dynamic_offset = loader_ctx->frame_csp->dynamic_offset;
-                    PUSH_OFFSET_TYPE(loader_ctx->frame_csp->return_type);
-                    wasm_loader_emit_backspace(loader_ctx, sizeof(int16));
-                }
+                /* copy the result to the block return address */
+                RESERVE_BLOCK_RET();
 
 
                 apply_label_patch(loader_ctx, 0, PATCH_END);
                 apply_label_patch(loader_ctx, 0, PATCH_END);
                 free_label_patch_list(loader_ctx->frame_csp);
                 free_label_patch_list(loader_ctx->frame_csp);
@@ -3892,24 +3942,13 @@ handle_next_reachable_block:
 
 
                 block_return_type = (loader_ctx->frame_csp - i)->return_type;
                 block_return_type = (loader_ctx->frame_csp - i)->return_type;
 
 
-                cache_index = ((uintptr_t)(loader_ctx->frame_csp - i)->start_addr)
-                              & (uintptr_t)(BLOCK_ADDR_CACHE_SIZE - 1);
-                cache_items = block_addr_cache + BLOCK_ADDR_CONFLICT_SIZE * cache_index;
-                for (item_index = 0; item_index < BLOCK_ADDR_CONFLICT_SIZE; item_index++) {
-                    if (cache_items[item_index].start_addr == (loader_ctx->frame_csp - i)->start_addr) {
-                        (loader_ctx->frame_csp - i)->else_addr = cache_items[item_index].else_addr;
-                        (loader_ctx->frame_csp - i)->end_addr = cache_items[item_index].end_addr;
-                        break;
-                    }
-                }
-                if(item_index == BLOCK_ADDR_CONFLICT_SIZE
-                   && !wasm_loader_find_block_addr(block_addr_cache,
-                                                   (loader_ctx->frame_csp - i)->start_addr,
-                                                   p_end,
-                                                   (loader_ctx->frame_csp - i)->block_type,
-                                                   &(loader_ctx->frame_csp - i)->else_addr,
-                                                   &(loader_ctx->frame_csp - i)->end_addr,
-                                                   error_buf, error_buf_size))
+                if(!wasm_loader_find_block_addr(block_addr_cache,
+                                    (loader_ctx->frame_csp - i)->start_addr,
+                                    p_end,
+                                    (loader_ctx->frame_csp - i)->block_type,
+                                    &(loader_ctx->frame_csp - i)->else_addr,
+                                    &(loader_ctx->frame_csp - i)->end_addr,
+                                    error_buf, error_buf_size))
                     goto fail;
                     goto fail;
 
 
                 loader_ctx->stack_cell_num = (loader_ctx->frame_csp - i)->stack_cell_num;
                 loader_ctx->stack_cell_num = (loader_ctx->frame_csp - i)->stack_cell_num;
@@ -4443,8 +4482,7 @@ handle_next_reachable_block:
                     case WASM_OP_I32_LOAD8_U:
                     case WASM_OP_I32_LOAD8_U:
                     case WASM_OP_I32_LOAD16_S:
                     case WASM_OP_I32_LOAD16_S:
                     case WASM_OP_I32_LOAD16_U:
                     case WASM_OP_I32_LOAD16_U:
-                        POP_I32();
-                        PUSH_I32();
+                        POP_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_I32);
                         break;
                         break;
                     case WASM_OP_I64_LOAD:
                     case WASM_OP_I64_LOAD:
                     case WASM_OP_I64_LOAD8_S:
                     case WASM_OP_I64_LOAD8_S:
@@ -4453,16 +4491,13 @@ handle_next_reachable_block:
                     case WASM_OP_I64_LOAD16_U:
                     case WASM_OP_I64_LOAD16_U:
                     case WASM_OP_I64_LOAD32_S:
                     case WASM_OP_I64_LOAD32_S:
                     case WASM_OP_I64_LOAD32_U:
                     case WASM_OP_I64_LOAD32_U:
-                        POP_I32();
-                        PUSH_I64();
+                        POP_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_I64);
                         break;
                         break;
                     case WASM_OP_F32_LOAD:
                     case WASM_OP_F32_LOAD:
-                        POP_I32();
-                        PUSH_F32();
+                        POP_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_F32);
                         break;
                         break;
                     case WASM_OP_F64_LOAD:
                     case WASM_OP_F64_LOAD:
-                        POP_I32();
-                        PUSH_F64();
+                        POP_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_F64);
                         break;
                         break;
                     /* store */
                     /* store */
                     case WASM_OP_I32_STORE:
                     case WASM_OP_I32_STORE:
@@ -4513,8 +4548,7 @@ handle_next_reachable_block:
                                   "zero flag expected");
                                   "zero flag expected");
                     goto fail;
                     goto fail;
                 }
                 }
-                POP_I32();
-                PUSH_I32();
+                POP_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_I32);
 
 
                 func->has_op_memory_grow = true;
                 func->has_op_memory_grow = true;
                 module->possible_memory_grow = true;
                 module->possible_memory_grow = true;
@@ -4566,8 +4600,7 @@ handle_next_reachable_block:
                 break;
                 break;
 
 
             case WASM_OP_I32_EQZ:
             case WASM_OP_I32_EQZ:
-                POP_I32();
-                PUSH_I32();
+                POP_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_I32);
                 break;
                 break;
 
 
             case WASM_OP_I32_EQ:
             case WASM_OP_I32_EQ:
@@ -4580,14 +4613,11 @@ handle_next_reachable_block:
             case WASM_OP_I32_LE_U:
             case WASM_OP_I32_LE_U:
             case WASM_OP_I32_GE_S:
             case WASM_OP_I32_GE_S:
             case WASM_OP_I32_GE_U:
             case WASM_OP_I32_GE_U:
-                POP_I32();
-                POP_I32();
-                PUSH_I32();
+                POP2_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_I32);
                 break;
                 break;
 
 
             case WASM_OP_I64_EQZ:
             case WASM_OP_I64_EQZ:
-                POP_I64();
-                PUSH_I32();
+                POP_AND_PUSH(VALUE_TYPE_I64, VALUE_TYPE_I32);
                 break;
                 break;
 
 
             case WASM_OP_I64_EQ:
             case WASM_OP_I64_EQ:
@@ -4600,9 +4630,7 @@ handle_next_reachable_block:
             case WASM_OP_I64_LE_U:
             case WASM_OP_I64_LE_U:
             case WASM_OP_I64_GE_S:
             case WASM_OP_I64_GE_S:
             case WASM_OP_I64_GE_U:
             case WASM_OP_I64_GE_U:
-                POP_I64();
-                POP_I64();
-                PUSH_I32();
+                POP2_AND_PUSH(VALUE_TYPE_I64, VALUE_TYPE_I32);
                 break;
                 break;
 
 
             case WASM_OP_F32_EQ:
             case WASM_OP_F32_EQ:
@@ -4611,9 +4639,7 @@ handle_next_reachable_block:
             case WASM_OP_F32_GT:
             case WASM_OP_F32_GT:
             case WASM_OP_F32_LE:
             case WASM_OP_F32_LE:
             case WASM_OP_F32_GE:
             case WASM_OP_F32_GE:
-                POP_F32();
-                POP_F32();
-                PUSH_I32();
+                POP2_AND_PUSH(VALUE_TYPE_F32, VALUE_TYPE_I32);
                 break;
                 break;
 
 
             case WASM_OP_F64_EQ:
             case WASM_OP_F64_EQ:
@@ -4622,9 +4648,7 @@ handle_next_reachable_block:
             case WASM_OP_F64_GT:
             case WASM_OP_F64_GT:
             case WASM_OP_F64_LE:
             case WASM_OP_F64_LE:
             case WASM_OP_F64_GE:
             case WASM_OP_F64_GE:
-                POP_F64();
-                POP_F64();
-                PUSH_I32();
+                POP2_AND_PUSH(VALUE_TYPE_F64, VALUE_TYPE_I32);
                 break;
                 break;
 
 
                 break;
                 break;
@@ -4632,8 +4656,7 @@ handle_next_reachable_block:
             case WASM_OP_I32_CLZ:
             case WASM_OP_I32_CLZ:
             case WASM_OP_I32_CTZ:
             case WASM_OP_I32_CTZ:
             case WASM_OP_I32_POPCNT:
             case WASM_OP_I32_POPCNT:
-                POP_I32();
-                PUSH_I32();
+                POP_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_I32);
                 break;
                 break;
 
 
             case WASM_OP_I32_ADD:
             case WASM_OP_I32_ADD:
@@ -4651,16 +4674,13 @@ handle_next_reachable_block:
             case WASM_OP_I32_SHR_U:
             case WASM_OP_I32_SHR_U:
             case WASM_OP_I32_ROTL:
             case WASM_OP_I32_ROTL:
             case WASM_OP_I32_ROTR:
             case WASM_OP_I32_ROTR:
-                POP_I32();
-                POP_I32();
-                PUSH_I32();
+                POP2_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_I32);
                 break;
                 break;
 
 
             case WASM_OP_I64_CLZ:
             case WASM_OP_I64_CLZ:
             case WASM_OP_I64_CTZ:
             case WASM_OP_I64_CTZ:
             case WASM_OP_I64_POPCNT:
             case WASM_OP_I64_POPCNT:
-                POP_I64();
-                PUSH_I64();
+                POP_AND_PUSH(VALUE_TYPE_I64, VALUE_TYPE_I64);
                 break;
                 break;
 
 
             case WASM_OP_I64_ADD:
             case WASM_OP_I64_ADD:
@@ -4678,9 +4698,7 @@ handle_next_reachable_block:
             case WASM_OP_I64_SHR_U:
             case WASM_OP_I64_SHR_U:
             case WASM_OP_I64_ROTL:
             case WASM_OP_I64_ROTL:
             case WASM_OP_I64_ROTR:
             case WASM_OP_I64_ROTR:
-                POP_I64();
-                POP_I64();
-                PUSH_I64();
+                POP2_AND_PUSH(VALUE_TYPE_I64, VALUE_TYPE_I64);
                 break;
                 break;
 
 
             case WASM_OP_F32_ABS:
             case WASM_OP_F32_ABS:
@@ -4690,8 +4708,7 @@ handle_next_reachable_block:
             case WASM_OP_F32_TRUNC:
             case WASM_OP_F32_TRUNC:
             case WASM_OP_F32_NEAREST:
             case WASM_OP_F32_NEAREST:
             case WASM_OP_F32_SQRT:
             case WASM_OP_F32_SQRT:
-                POP_F32();
-                PUSH_F32();
+                POP_AND_PUSH(VALUE_TYPE_F32, VALUE_TYPE_F32);
                 break;
                 break;
 
 
             case WASM_OP_F32_ADD:
             case WASM_OP_F32_ADD:
@@ -4701,9 +4718,7 @@ handle_next_reachable_block:
             case WASM_OP_F32_MIN:
             case WASM_OP_F32_MIN:
             case WASM_OP_F32_MAX:
             case WASM_OP_F32_MAX:
             case WASM_OP_F32_COPYSIGN:
             case WASM_OP_F32_COPYSIGN:
-                POP_F32();
-                POP_F32();
-                PUSH_F32();
+                POP2_AND_PUSH(VALUE_TYPE_F32, VALUE_TYPE_F32);
                 break;
                 break;
 
 
             case WASM_OP_F64_ABS:
             case WASM_OP_F64_ABS:
@@ -4713,8 +4728,7 @@ handle_next_reachable_block:
             case WASM_OP_F64_TRUNC:
             case WASM_OP_F64_TRUNC:
             case WASM_OP_F64_NEAREST:
             case WASM_OP_F64_NEAREST:
             case WASM_OP_F64_SQRT:
             case WASM_OP_F64_SQRT:
-                POP_F64();
-                PUSH_F64();
+                POP_AND_PUSH(VALUE_TYPE_F64, VALUE_TYPE_F64);
                 break;
                 break;
 
 
             case WASM_OP_F64_ADD:
             case WASM_OP_F64_ADD:
@@ -4724,111 +4738,91 @@ handle_next_reachable_block:
             case WASM_OP_F64_MIN:
             case WASM_OP_F64_MIN:
             case WASM_OP_F64_MAX:
             case WASM_OP_F64_MAX:
             case WASM_OP_F64_COPYSIGN:
             case WASM_OP_F64_COPYSIGN:
-                POP_F64();
-                POP_F64();
-                PUSH_F64();
+                POP2_AND_PUSH(VALUE_TYPE_F64, VALUE_TYPE_F64);
                 break;
                 break;
 
 
             case WASM_OP_I32_WRAP_I64:
             case WASM_OP_I32_WRAP_I64:
-                POP_I64();
-                PUSH_I32();
+                POP_AND_PUSH(VALUE_TYPE_I64, VALUE_TYPE_I32);
                 break;
                 break;
 
 
             case WASM_OP_I32_TRUNC_S_F32:
             case WASM_OP_I32_TRUNC_S_F32:
             case WASM_OP_I32_TRUNC_U_F32:
             case WASM_OP_I32_TRUNC_U_F32:
-                POP_F32();
-                PUSH_I32();
+                POP_AND_PUSH(VALUE_TYPE_F32, VALUE_TYPE_I32);
                 break;
                 break;
 
 
             case WASM_OP_I32_TRUNC_S_F64:
             case WASM_OP_I32_TRUNC_S_F64:
             case WASM_OP_I32_TRUNC_U_F64:
             case WASM_OP_I32_TRUNC_U_F64:
-                POP_F64();
-                PUSH_I32();
+                POP_AND_PUSH(VALUE_TYPE_F64, VALUE_TYPE_I32);
                 break;
                 break;
 
 
             case WASM_OP_I64_EXTEND_S_I32:
             case WASM_OP_I64_EXTEND_S_I32:
             case WASM_OP_I64_EXTEND_U_I32:
             case WASM_OP_I64_EXTEND_U_I32:
-                POP_I32();
-                PUSH_I64();
+                POP_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_I64);
                 break;
                 break;
 
 
             case WASM_OP_I64_TRUNC_S_F32:
             case WASM_OP_I64_TRUNC_S_F32:
             case WASM_OP_I64_TRUNC_U_F32:
             case WASM_OP_I64_TRUNC_U_F32:
-                POP_F32();
-                PUSH_I64();
+                POP_AND_PUSH(VALUE_TYPE_F32, VALUE_TYPE_I64);
                 break;
                 break;
 
 
             case WASM_OP_I64_TRUNC_S_F64:
             case WASM_OP_I64_TRUNC_S_F64:
             case WASM_OP_I64_TRUNC_U_F64:
             case WASM_OP_I64_TRUNC_U_F64:
-                POP_F64();
-                PUSH_I64();
+                POP_AND_PUSH(VALUE_TYPE_F64, VALUE_TYPE_I64);
                 break;
                 break;
 
 
             case WASM_OP_F32_CONVERT_S_I32:
             case WASM_OP_F32_CONVERT_S_I32:
             case WASM_OP_F32_CONVERT_U_I32:
             case WASM_OP_F32_CONVERT_U_I32:
-                POP_I32();
-                PUSH_F32();
+                POP_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_F32);
                 break;
                 break;
 
 
             case WASM_OP_F32_CONVERT_S_I64:
             case WASM_OP_F32_CONVERT_S_I64:
             case WASM_OP_F32_CONVERT_U_I64:
             case WASM_OP_F32_CONVERT_U_I64:
-                POP_I64();
-                PUSH_F32();
+                POP_AND_PUSH(VALUE_TYPE_I64, VALUE_TYPE_F32);
                 break;
                 break;
 
 
             case WASM_OP_F32_DEMOTE_F64:
             case WASM_OP_F32_DEMOTE_F64:
-                POP_F64();
-                PUSH_F32();
+                POP_AND_PUSH(VALUE_TYPE_F64, VALUE_TYPE_F32);
                 break;
                 break;
 
 
             case WASM_OP_F64_CONVERT_S_I32:
             case WASM_OP_F64_CONVERT_S_I32:
             case WASM_OP_F64_CONVERT_U_I32:
             case WASM_OP_F64_CONVERT_U_I32:
-                POP_I32();
-                PUSH_F64();
+                POP_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_F64);
                 break;
                 break;
 
 
             case WASM_OP_F64_CONVERT_S_I64:
             case WASM_OP_F64_CONVERT_S_I64:
             case WASM_OP_F64_CONVERT_U_I64:
             case WASM_OP_F64_CONVERT_U_I64:
-                POP_I64();
-                PUSH_F64();
+                POP_AND_PUSH(VALUE_TYPE_I64, VALUE_TYPE_F64);
                 break;
                 break;
 
 
             case WASM_OP_F64_PROMOTE_F32:
             case WASM_OP_F64_PROMOTE_F32:
-                POP_F32();
-                PUSH_F64();
+                POP_AND_PUSH(VALUE_TYPE_F32, VALUE_TYPE_F64);
                 break;
                 break;
 
 
             case WASM_OP_I32_REINTERPRET_F32:
             case WASM_OP_I32_REINTERPRET_F32:
-                POP_F32();
-                PUSH_I32();
+                POP_AND_PUSH(VALUE_TYPE_F32, VALUE_TYPE_I32);
                 break;
                 break;
 
 
             case WASM_OP_I64_REINTERPRET_F64:
             case WASM_OP_I64_REINTERPRET_F64:
-                POP_F64();
-                PUSH_I64();
+                POP_AND_PUSH(VALUE_TYPE_F64, VALUE_TYPE_I64);
                 break;
                 break;
 
 
             case WASM_OP_F32_REINTERPRET_I32:
             case WASM_OP_F32_REINTERPRET_I32:
-                POP_I32();
-                PUSH_F32();
+                POP_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_F32);
                 break;
                 break;
 
 
             case WASM_OP_F64_REINTERPRET_I64:
             case WASM_OP_F64_REINTERPRET_I64:
-                POP_I64();
-                PUSH_F64();
+                POP_AND_PUSH(VALUE_TYPE_I64, VALUE_TYPE_F64);
                 break;
                 break;
 
 
             case WASM_OP_I32_EXTEND8_S:
             case WASM_OP_I32_EXTEND8_S:
             case WASM_OP_I32_EXTEND16_S:
             case WASM_OP_I32_EXTEND16_S:
-                POP_I32();
-                PUSH_I32();
+                POP_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_I32);
                 break;
                 break;
 
 
             case WASM_OP_I64_EXTEND8_S:
             case WASM_OP_I64_EXTEND8_S:
             case WASM_OP_I64_EXTEND16_S:
             case WASM_OP_I64_EXTEND16_S:
             case WASM_OP_I64_EXTEND32_S:
             case WASM_OP_I64_EXTEND32_S:
-                POP_I64();
-                PUSH_I64();
+                POP_AND_PUSH(VALUE_TYPE_I64, VALUE_TYPE_I64);
                 break;
                 break;
 
 
             case WASM_OP_MISC_PREFIX:
             case WASM_OP_MISC_PREFIX:
@@ -4841,23 +4835,19 @@ handle_next_reachable_block:
                 {
                 {
                 case WASM_OP_I32_TRUNC_SAT_S_F32:
                 case WASM_OP_I32_TRUNC_SAT_S_F32:
                 case WASM_OP_I32_TRUNC_SAT_U_F32:
                 case WASM_OP_I32_TRUNC_SAT_U_F32:
-                    POP_F32();
-                    PUSH_I32();
+                    POP_AND_PUSH(VALUE_TYPE_F32, VALUE_TYPE_I32);
                     break;
                     break;
                 case WASM_OP_I32_TRUNC_SAT_S_F64:
                 case WASM_OP_I32_TRUNC_SAT_S_F64:
                 case WASM_OP_I32_TRUNC_SAT_U_F64:
                 case WASM_OP_I32_TRUNC_SAT_U_F64:
-                    POP_F64();
-                    PUSH_I32();
+                    POP_AND_PUSH(VALUE_TYPE_F64, VALUE_TYPE_I32);
                     break;
                     break;
                 case WASM_OP_I64_TRUNC_SAT_S_F32:
                 case WASM_OP_I64_TRUNC_SAT_S_F32:
                 case WASM_OP_I64_TRUNC_SAT_U_F32:
                 case WASM_OP_I64_TRUNC_SAT_U_F32:
-                    POP_F32();
-                    PUSH_I64();
+                    POP_AND_PUSH(VALUE_TYPE_F32, VALUE_TYPE_I64);
                     break;
                     break;
                 case WASM_OP_I64_TRUNC_SAT_S_F64:
                 case WASM_OP_I64_TRUNC_SAT_S_F64:
                 case WASM_OP_I64_TRUNC_SAT_U_F64:
                 case WASM_OP_I64_TRUNC_SAT_U_F64:
-                    POP_F64();
-                    PUSH_I64();
+                    POP_AND_PUSH(VALUE_TYPE_F64, VALUE_TYPE_I64);
                     break;
                     break;
                 default:
                 default:
                     if (error_buf != NULL)
                     if (error_buf != NULL)

+ 0 - 4
core/iwasm/interpreter/wasm_runtime.c

@@ -818,10 +818,6 @@ wasm_deinstantiate(WASMModuleInstance *module_inst)
 
 
     if (module_inst->memory_count > 0)
     if (module_inst->memory_count > 0)
         memories_deinstantiate(module_inst->memories, module_inst->memory_count);
         memories_deinstantiate(module_inst->memories, module_inst->memory_count);
-    else if (module_inst->memories != NULL && module_inst->global_count > 0)
-        /* No imported memory and defined memory, the memory is created when
-           global count > 0. */
-        memories_deinstantiate(module_inst->memories, 1);
 
 
     tables_deinstantiate(module_inst->tables, module_inst->table_count);
     tables_deinstantiate(module_inst->tables, module_inst->table_count);
     functions_deinstantiate(module_inst->functions, module_inst->function_count);
     functions_deinstantiate(module_inst->functions, module_inst->function_count);

+ 23 - 11
core/shared/platform/common/posix/posix_thread.c

@@ -223,19 +223,31 @@ int os_thread_join(korp_tid thread, void **value_ptr)
 
 
 uint8 *os_thread_get_stack_boundary()
 uint8 *os_thread_get_stack_boundary()
 {
 {
+    pthread_t self = pthread_self();
     pthread_attr_t attr;
     pthread_attr_t attr;
-    void *addr = NULL;
-    size_t size;
-
-    if (pthread_getattr_np(pthread_self(), &attr) == 0) {
-        pthread_attr_getstack(&attr, &addr, &size);
-        pthread_attr_destroy (&attr);
+    uint8 *addr = NULL;
+    size_t stack_size, guard_size;
+
+#ifdef __linux__
+    if (pthread_getattr_np(self, &attr) == 0) {
+        pthread_attr_getstack(&attr, (void**)&addr, &stack_size);
+        pthread_attr_getguardsize(&attr, &guard_size);
+        pthread_attr_destroy(&attr);
+        if (guard_size < 4 * 1024)
+            /* Reserved 4 KB guard size at least for safety */
+            guard_size = 4 * 1024;
+        addr += guard_size;
+    }
+    (void)stack_size;
+#elif defined(__APPLE__)
+    if ((addr = (uint8*)pthread_get_stackaddr_np(self))) {
+        stack_size = pthread_get_stacksize_np(self);
+        addr -= stack_size;
+        /* Reserved 4 KB guard size at least for safety */
+        addr += 4 * 1024;
     }
     }
+#endif
 
 
-    if (addr)
-        /* Reserved 4 KB for safety */
-        return (uint8*)addr + 4 * 1024;
-    else
-        return NULL;
+    return addr;
 }
 }