Explorar el Código

Implement aot_alloc_frame/aot_free_frame with LLVM IRs (#2830)

Wenyong Huang hace 2 años
padre
commit
cf7350f069

+ 2 - 1
core/iwasm/aot/aot_reloc.h

@@ -56,7 +56,8 @@ typedef struct {
 #if WASM_ENABLE_AOT_STACK_FRAME != 0
 #define REG_AOT_TRACE_SYM()               \
     REG_SYM(aot_alloc_frame),             \
-    REG_SYM(aot_free_frame),
+    REG_SYM(aot_free_frame),              \
+    REG_SYM(aot_frame_update_profile_info),
 #else
 #define REG_AOT_TRACE_SYM()
 #endif

+ 41 - 0
core/iwasm/aot/aot_runtime.c

@@ -34,6 +34,12 @@ bh_static_assert(offsetof(WASMExecEnv, aux_stack_bottom)
 bh_static_assert(offsetof(WASMExecEnv, native_symbol) == 8 * sizeof(uintptr_t));
 bh_static_assert(offsetof(WASMExecEnv, native_stack_top_min)
                  == 9 * sizeof(uintptr_t));
+bh_static_assert(offsetof(WASMExecEnv, wasm_stack.top_boundary)
+                 == 10 * sizeof(uintptr_t));
+bh_static_assert(offsetof(WASMExecEnv, wasm_stack.top)
+                 == 11 * sizeof(uintptr_t));
+bh_static_assert(offsetof(WASMExecEnv, wasm_stack.bottom)
+                 == 12 * sizeof(uintptr_t));
 
 bh_static_assert(offsetof(AOTModuleInstance, memories) == 1 * sizeof(uint64));
 bh_static_assert(offsetof(AOTModuleInstance, func_ptrs) == 5 * sizeof(uint64));
@@ -49,6 +55,11 @@ bh_static_assert(offsetof(AOTTableInstance, elems) == 24);
 
 bh_static_assert(offsetof(AOTModuleInstanceExtra, stack_sizes) == 0);
 
+bh_static_assert(offsetof(AOTFrame, prev_frame) == sizeof(uintptr_t) * 0);
+bh_static_assert(offsetof(AOTFrame, func_index) == sizeof(uintptr_t) * 1);
+bh_static_assert(offsetof(AOTFrame, time_started) == sizeof(uintptr_t) * 2);
+bh_static_assert(offsetof(AOTFrame, func_perf_prof_info)
+                 == sizeof(uintptr_t) * 3);
 bh_static_assert(offsetof(AOTFrame, ip_offset) == sizeof(uintptr_t) * 4);
 bh_static_assert(offsetof(AOTFrame, sp) == sizeof(uintptr_t) * 5);
 bh_static_assert(offsetof(AOTFrame, frame_ref) == sizeof(uintptr_t) * 6);
@@ -3554,6 +3565,36 @@ aot_free_frame(WASMExecEnv *exec_env)
     wasm_exec_env_free_wasm_frame(exec_env, cur_frame);
     exec_env->cur_frame = (struct WASMInterpFrame *)prev_frame;
 }
+
+void
+aot_frame_update_profile_info(WASMExecEnv *exec_env, bool alloc_frame)
+{
+#if WASM_ENABLE_PERF_PROFILING != 0
+    AOTFrame *cur_frame = (AOTFrame *)exec_env->cur_frame;
+    AOTModuleInstance *module_inst = (AOTModuleInstance *)exec_env->module_inst;
+    AOTFuncPerfProfInfo *func_perf_prof =
+        module_inst->func_perf_profilings + cur_frame->func_index;
+
+    if (alloc_frame) {
+        cur_frame->time_started = (uintptr_t)os_time_get_boot_microsecond();
+        cur_frame->func_perf_prof_info = func_perf_prof;
+    }
+    else {
+        cur_frame->func_perf_prof_info->total_exec_time +=
+            (uintptr_t)os_time_get_boot_microsecond() - cur_frame->time_started;
+        cur_frame->func_perf_prof_info->total_exec_cnt++;
+    }
+#endif
+
+#if WASM_ENABLE_MEMORY_PROFILING != 0
+    if (alloc_frame) {
+        uint32 wasm_stack_used =
+            exec_env->wasm_stack.top - exec_env->wasm_stack.bottom;
+        if (wasm_stack_used > exec_env->max_wasm_stack_used)
+            exec_env->max_wasm_stack_used = wasm_stack_used;
+    }
+#endif
+}
 #endif /* end of WASM_ENABLE_AOT_STACK_FRAME != 0 */
 
 #if WASM_ENABLE_DUMP_CALL_STACK != 0

+ 3 - 0
core/iwasm/aot/aot_runtime.h

@@ -660,6 +660,9 @@ aot_alloc_frame(WASMExecEnv *exec_env, uint32 func_index);
 void
 aot_free_frame(WASMExecEnv *exec_env);
 
+void
+aot_frame_update_profile_info(WASMExecEnv *exec_env, bool alloc_frame);
+
 bool
 aot_create_call_stack(struct WASMExecEnv *exec_env);
 

+ 5 - 4
core/iwasm/common/wasm_exec_env.c

@@ -31,7 +31,7 @@ wasm_exec_env_create_internal(struct WASMModuleInstanceCommon *module_inst,
                               uint32 stack_size)
 {
     uint64 total_size =
-        offsetof(WASMExecEnv, wasm_stack.s.bottom) + (uint64)stack_size;
+        offsetof(WASMExecEnv, wasm_stack_u.bottom) + (uint64)stack_size;
     WASMExecEnv *exec_env;
 
     if (total_size >= UINT32_MAX
@@ -68,9 +68,10 @@ wasm_exec_env_create_internal(struct WASMModuleInstanceCommon *module_inst,
 
     exec_env->module_inst = module_inst;
     exec_env->wasm_stack_size = stack_size;
-    exec_env->wasm_stack.s.top_boundary =
-        exec_env->wasm_stack.s.bottom + stack_size;
-    exec_env->wasm_stack.s.top = exec_env->wasm_stack.s.bottom;
+    exec_env->wasm_stack.bottom = exec_env->wasm_stack_u.bottom;
+    exec_env->wasm_stack.top_boundary =
+        exec_env->wasm_stack.bottom + stack_size;
+    exec_env->wasm_stack.top = exec_env->wasm_stack.bottom;
 
 #if WASM_ENABLE_AOT != 0
     if (module_inst->module_type == Wasm_Module_AoT) {

+ 19 - 19
core/iwasm/common/wasm_exec_env.h

@@ -84,6 +84,15 @@ typedef struct WASMExecEnv {
      */
     uint8 *native_stack_top_min;
 
+    struct {
+        /* The top boundary of the stack. */
+        uint8 *top_boundary;
+        /* The top to of the wasm stack which is free. */
+        uint8 *top;
+        /* The bottom of the wasm stack. */
+        uint8 *bottom;
+    } wasm_stack;
+
 #if WASM_ENABLE_FAST_JIT != 0
     /**
      * Cache for
@@ -153,18 +162,9 @@ typedef struct WASMExecEnv {
     /* The WASM stack of current thread */
     union {
         uint64 __make_it_8_byte_aligned_;
-
-        struct {
-            /* The top boundary of the stack. */
-            uint8 *top_boundary;
-
-            /* Top cell index which is free. */
-            uint8 *top;
-
-            /* The WASM stack. */
-            uint8 bottom[1];
-        } s;
-    } wasm_stack;
+        /* The WASM stack. */
+        uint8 bottom[1];
+    } wasm_stack_u;
 } WASMExecEnv;
 
 #if WASM_ENABLE_MEMORY_PROFILING != 0
@@ -211,7 +211,7 @@ wasm_exec_env_is_aux_stack_managed_by_runtime(WASMExecEnv *exec_env)
 static inline void *
 wasm_exec_env_alloc_wasm_frame(WASMExecEnv *exec_env, unsigned size)
 {
-    uint8 *addr = exec_env->wasm_stack.s.top;
+    uint8 *addr = exec_env->wasm_stack.top;
 
     bh_assert(!(size & 3));
 
@@ -222,17 +222,17 @@ wasm_exec_env_alloc_wasm_frame(WASMExecEnv *exec_env, unsigned size)
        frame size, we should check again before putting the function arguments
        into the outs area. */
     if (size * 2
-        > (uint32)(uintptr_t)(exec_env->wasm_stack.s.top_boundary - addr)) {
+        > (uint32)(uintptr_t)(exec_env->wasm_stack.top_boundary - addr)) {
         /* WASM stack overflow. */
         return NULL;
     }
 
-    exec_env->wasm_stack.s.top += size;
+    exec_env->wasm_stack.top += size;
 
 #if WASM_ENABLE_MEMORY_PROFILING != 0
     {
         uint32 wasm_stack_used =
-            exec_env->wasm_stack.s.top - exec_env->wasm_stack.s.bottom;
+            exec_env->wasm_stack.top - exec_env->wasm_stack.bottom;
         if (wasm_stack_used > exec_env->max_wasm_stack_used)
             exec_env->max_wasm_stack_used = wasm_stack_used;
     }
@@ -243,8 +243,8 @@ wasm_exec_env_alloc_wasm_frame(WASMExecEnv *exec_env, unsigned size)
 static inline void
 wasm_exec_env_free_wasm_frame(WASMExecEnv *exec_env, void *prev_top)
 {
-    bh_assert((uint8 *)prev_top >= exec_env->wasm_stack.s.bottom);
-    exec_env->wasm_stack.s.top = (uint8 *)prev_top;
+    bh_assert((uint8 *)prev_top >= exec_env->wasm_stack.bottom);
+    exec_env->wasm_stack.top = (uint8 *)prev_top;
 }
 
 /**
@@ -257,7 +257,7 @@ wasm_exec_env_free_wasm_frame(WASMExecEnv *exec_env, void *prev_top)
 static inline void *
 wasm_exec_env_wasm_stack_top(WASMExecEnv *exec_env)
 {
-    return exec_env->wasm_stack.s.top;
+    return exec_env->wasm_stack.top;
 }
 
 /**

+ 6 - 6
core/iwasm/common/wasm_runtime_common.c

@@ -557,9 +557,9 @@ static bool
 wasm_runtime_exec_env_check(WASMExecEnv *exec_env)
 {
     return exec_env && exec_env->module_inst && exec_env->wasm_stack_size > 0
-           && exec_env->wasm_stack.s.top_boundary
-                  == exec_env->wasm_stack.s.bottom + exec_env->wasm_stack_size
-           && exec_env->wasm_stack.s.top <= exec_env->wasm_stack.s.top_boundary;
+           && exec_env->wasm_stack.top_boundary
+                  == exec_env->wasm_stack.bottom + exec_env->wasm_stack_size
+           && exec_env->wasm_stack.top <= exec_env->wasm_stack.top_boundary;
 }
 
 bool
@@ -1578,11 +1578,11 @@ void
 wasm_runtime_dump_exec_env_mem_consumption(const WASMExecEnv *exec_env)
 {
     uint32 total_size =
-        offsetof(WASMExecEnv, wasm_stack.s.bottom) + exec_env->wasm_stack_size;
+        offsetof(WASMExecEnv, wasm_stack_u.bottom) + exec_env->wasm_stack_size;
 
     os_printf("Exec env memory consumption, total size: %u\n", total_size);
     os_printf("    exec env struct size: %u\n",
-              offsetof(WASMExecEnv, wasm_stack.s.bottom));
+              offsetof(WASMExecEnv, wasm_stack_u.bottom));
 #if WASM_ENABLE_INTERP != 0 && WASM_ENABLE_FAST_INTERP == 0
     os_printf("        block addr cache size: %u\n",
               sizeof(exec_env->block_addr_cache));
@@ -1643,7 +1643,7 @@ wasm_runtime_dump_mem_consumption(WASMExecEnv *exec_env)
         app_heap_peak_size = gc_get_heap_highmark_size(heap_handle);
     }
 
-    total_size = offsetof(WASMExecEnv, wasm_stack.s.bottom)
+    total_size = offsetof(WASMExecEnv, wasm_stack_u.bottom)
                  + exec_env->wasm_stack_size + module_mem_consps.total_size
                  + module_inst_mem_consps.total_size;
 

+ 108 - 96
core/iwasm/compilation/aot_compiler.c

@@ -170,29 +170,7 @@ uint32
 offset_of_local_in_outs_area(AOTCompContext *comp_ctx, unsigned n)
 {
     AOTCompFrame *frame = comp_ctx->aot_frame;
-    uint32 max_local_cell_num = frame->max_local_cell_num;
-    uint32 max_stack_cell_num = frame->max_stack_cell_num;
-    uint32 all_cell_num = max_local_cell_num + max_stack_cell_num;
-    uint32 frame_size;
-
-    if (!comp_ctx->is_jit_mode) {
-        /* Refer to aot_alloc_frame */
-        if (!comp_ctx->enable_gc)
-            frame_size = comp_ctx->pointer_size * 7 + all_cell_num * 4;
-        else
-            frame_size =
-                comp_ctx->pointer_size * 7 + align_uint(all_cell_num * 5, 4);
-    }
-    else {
-        /* Refer to wasm_interp_interp_frame_size */
-        if (!comp_ctx->enable_gc)
-            frame_size = offsetof(WASMInterpFrame, lp) + all_cell_num * 4;
-        else
-            frame_size =
-                offsetof(WASMInterpFrame, lp) + align_uint(all_cell_num * 5, 4);
-    }
-
-    return frame_size + offset_of_local(comp_ctx, n);
+    return frame->cur_frame_size + offset_of_local(comp_ctx, n);
 }
 
 static bool
@@ -566,6 +544,9 @@ aot_gen_commit_sp_ip(AOTCompFrame *frame, const AOTValueSlot *sp,
     LLVMTypeRef int8_ptr_ptr_type;
     uint32 offset_ip, offset_sp, n;
     bool is_64bit = (comp_ctx->pointer_size == sizeof(uint64)) ? true : false;
+    /* TODO: only commit sp currently, will add more options to
+       control whether to commit sp/ip in the future */
+    bool commit_sp = true, commit_ip = false;
 
     if (!comp_ctx->is_jit_mode) {
         offset_ip = frame->comp_ctx->pointer_size * 4;
@@ -576,97 +557,126 @@ aot_gen_commit_sp_ip(AOTCompFrame *frame, const AOTValueSlot *sp,
         offset_sp = offsetof(WASMInterpFrame, sp);
     }
 
-    /* commit ip */
+    if (commit_ip) {
+        if (!(value_offset = I32_CONST(offset_ip))) {
+            aot_set_last_error("llvm build const failed");
+            return false;
+        }
 
-    if (!(value_offset = I32_CONST(offset_ip))) {
-        aot_set_last_error("llvm build const failed");
-        return false;
-    }
+        if (!(value_addr =
+                  LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE, cur_frame,
+                                        &value_offset, 1, "ip_addr"))) {
+            aot_set_last_error("llvm build in bounds gep failed");
+            return false;
+        }
 
-    if (!(value_addr =
-              LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE, cur_frame,
-                                    &value_offset, 1, "ip_addr"))) {
-        aot_set_last_error("llvm build in bounds gep failed");
-        return false;
-    }
+        if (!(value_ptr = LLVMBuildBitCast(
+                  comp_ctx->builder, value_addr,
+                  is_64bit ? INT64_PTR_TYPE : INT32_PTR_TYPE, "ip_ptr"))) {
+            aot_set_last_error("llvm build bit cast failed");
+            return false;
+        }
 
-    if (!(value_ptr = LLVMBuildBitCast(
-              comp_ctx->builder, value_addr,
-              is_64bit ? INT64_PTR_TYPE : INT32_PTR_TYPE, "ip_ptr"))) {
-        aot_set_last_error("llvm build bit cast failed");
-        return false;
-    }
+        if (!comp_ctx->is_jit_mode) {
+            if (is_64bit)
+                value = I64_CONST(
+                    (uint64)(uintptr_t)(ip - func_ctx->aot_func->code));
+            else
+                value = I32_CONST(
+                    (uint32)(uintptr_t)(ip - func_ctx->aot_func->code));
+        }
+        else {
+            if (is_64bit)
+                value = I64_CONST((uint64)(uintptr_t)ip);
+            else
+                value = I32_CONST((uint32)(uintptr_t)ip);
+        }
 
-    if (!comp_ctx->is_jit_mode) {
-        if (is_64bit)
-            value =
-                I64_CONST((uint64)(uintptr_t)(ip - func_ctx->aot_func->code));
-        else
-            value =
-                I32_CONST((uint32)(uintptr_t)(ip - func_ctx->aot_func->code));
-    }
-    else {
-        if (is_64bit)
-            value = I64_CONST((uint64)(uintptr_t)ip);
-        else
-            value = I32_CONST((uint32)(uintptr_t)ip);
-    }
+        if (!value) {
+            aot_set_last_error("llvm build const failed");
+            return false;
+        }
 
-    if (!value) {
-        aot_set_last_error("llvm build const failed");
-        return false;
+        if (!LLVMBuildStore(comp_ctx->builder, value, value_ptr)) {
+            aot_set_last_error("llvm build store failed");
+            return false;
+        }
     }
 
-    if (!LLVMBuildStore(comp_ctx->builder, value, value_ptr)) {
-        aot_set_last_error("llvm build store failed");
-        return false;
-    }
+    if (commit_sp) {
+        n = sp - frame->lp;
+        value = I32_CONST(offset_of_local(comp_ctx, n));
+        if (!value) {
+            aot_set_last_error("llvm build const failed");
+            return false;
+        }
 
-    /* commit sp */
+        if (!(value = LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE,
+                                            cur_frame, &value, 1, "sp"))) {
+            aot_set_last_error("llvm build in bounds gep failed");
+            return false;
+        }
 
-    n = sp - frame->lp;
-    value = I32_CONST(offset_of_local(comp_ctx, n));
-    if (!value) {
-        aot_set_last_error("llvm build const failed");
-        return false;
-    }
+        if (!(value_offset = I32_CONST(offset_sp))) {
+            aot_set_last_error("llvm build const failed");
+            return false;
+        }
 
-    if (!(value = LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE, cur_frame,
-                                        &value, 1, "sp"))) {
-        aot_set_last_error("llvm build in bounds gep failed");
-        return false;
-    }
+        if (!(value_addr =
+                  LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE, cur_frame,
+                                        &value_offset, 1, "sp_addr"))) {
+            aot_set_last_error("llvm build in bounds gep failed");
+            return false;
+        }
 
-    if (!(value_offset = I32_CONST(offset_sp))) {
-        aot_set_last_error("llvm build const failed");
-        return false;
-    }
+        if (!(int8_ptr_ptr_type = LLVMPointerType(INT8_PTR_TYPE, 0))) {
+            aot_set_last_error("llvm build pointer type failed");
+            return false;
+        }
 
-    if (!(value_addr =
-              LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE, cur_frame,
-                                    &value_offset, 1, "sp_addr"))) {
-        aot_set_last_error("llvm build in bounds gep failed");
-        return false;
-    }
+        if (!(value_ptr = LLVMBuildBitCast(comp_ctx->builder, value_addr,
+                                           int8_ptr_ptr_type, "sp_ptr"))) {
+            aot_set_last_error("llvm build bit cast failed");
+            return false;
+        }
 
-    if (!(int8_ptr_ptr_type = LLVMPointerType(INT8_PTR_TYPE, 0))) {
-        aot_set_last_error("llvm build pointer type failed");
-        return false;
+        if (!LLVMBuildStore(comp_ctx->builder, value, value_ptr)) {
+            aot_set_last_error("llvm build store failed");
+            return false;
+        }
     }
 
-    if (!(value_ptr = LLVMBuildBitCast(comp_ctx->builder, value_addr,
-                                       int8_ptr_ptr_type, "sp_ptr"))) {
-        aot_set_last_error("llvm build bit cast failed");
-        return false;
-    }
+    return true;
+}
 
-    if (!LLVMBuildStore(comp_ctx->builder, value, value_ptr)) {
-        aot_set_last_error("llvm build store failed");
-        return false;
+static uint32
+get_cur_frame_size(const AOTCompContext *comp_ctx, uint32 max_local_cell_num,
+                   uint32 max_stack_cell_num)
+{
+    uint32 all_cell_num = max_local_cell_num + max_stack_cell_num;
+    uint32 frame_size;
+
+    if (!comp_ctx->is_jit_mode) {
+        /* Refer to aot_alloc_frame */
+        if (!comp_ctx->enable_gc)
+            frame_size = comp_ctx->pointer_size
+                             * (offsetof(AOTFrame, lp) / sizeof(uintptr_t))
+                         + all_cell_num * 4;
+        else
+            frame_size = comp_ctx->pointer_size
+                             * (offsetof(AOTFrame, lp) / sizeof(uintptr_t))
+                         + align_uint(all_cell_num * 5, 4);
+    }
+    else {
+        /* Refer to wasm_interp_interp_frame_size */
+        if (!comp_ctx->enable_gc)
+            frame_size = offsetof(WASMInterpFrame, lp) + all_cell_num * 4;
+        else
+            frame_size =
+                offsetof(WASMInterpFrame, lp) + align_uint(all_cell_num * 5, 4);
     }
 
-    /* commit sp */
-    return true;
+    return frame_size;
 }
 
 static bool
@@ -715,6 +725,8 @@ init_comp_frame(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
 
     aot_frame->max_local_cell_num = max_local_cell_num;
     aot_frame->max_stack_cell_num = max_stack_cell_num;
+    aot_frame->cur_frame_size =
+        get_cur_frame_size(comp_ctx, max_local_cell_num, max_stack_cell_num);
 
     aot_frame->sp = aot_frame->lp + max_local_cell_num;
 

+ 8 - 1
core/iwasm/compilation/aot_compiler.h

@@ -9,6 +9,7 @@
 #include "aot.h"
 #include "aot_llvm.h"
 #include "../interpreter/wasm_interp.h"
+#include "../aot/aot_runtime.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -150,7 +151,9 @@ offset_of_local(AOTCompContext *comp_ctx, unsigned n)
 {
     if (!comp_ctx->is_jit_mode)
         /* In AOTFrame, there are 7 pointers before field lp */
-        return comp_ctx->pointer_size * 7 + sizeof(uint32) * n;
+        return comp_ctx->pointer_size
+                   * (offsetof(AOTFrame, lp) / sizeof(uintptr_t))
+               + sizeof(uint32) * n;
     else
         return offsetof(WASMInterpFrame, lp) + sizeof(uint32) * n;
 }
@@ -627,6 +630,7 @@ set_local_gc_ref(AOTCompFrame *frame, int n, LLVMValueRef value, uint8 ref_type)
 #define I1_ZERO LLVM_CONST(i1_zero)
 #define I1_ONE LLVM_CONST(i1_one)
 #define I8_ZERO LLVM_CONST(i8_zero)
+#define I8_ONE LLVM_CONST(i8_one)
 #define I32_ZERO LLVM_CONST(i32_zero)
 #define I64_ZERO LLVM_CONST(i64_zero)
 #define F32_ZERO LLVM_CONST(f32_zero)
@@ -640,6 +644,9 @@ set_local_gc_ref(AOTCompFrame *frame, int n, LLVMValueRef value, uint8 ref_type)
 #define I32_SEVEN LLVM_CONST(i32_seven)
 #define I32_EIGHT LLVM_CONST(i32_eight)
 #define I32_NINE LLVM_CONST(i32_nine)
+#define I32_TEN LLVM_CONST(i32_ten)
+#define I32_ELEVEN LLVM_CONST(i32_eleven)
+#define I32_TWELVE LLVM_CONST(i32_twelve)
 #define I32_NEG_ONE LLVM_CONST(i32_neg_one)
 #define I64_NEG_ONE LLVM_CONST(i64_neg_one)
 #define I32_MIN LLVM_CONST(i32_min)

+ 31 - 13
core/iwasm/compilation/aot_emit_control.c

@@ -933,9 +933,13 @@ aot_compile_op_br(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
             return false;
 
         if (block_dst->label_type == LABEL_TYPE_LOOP) {
-            if (!aot_gen_commit_sp_ip(comp_ctx->aot_frame,
-                                      comp_ctx->aot_frame->sp, frame_ip_br))
-                return false;
+#if WASM_ENABLE_THREAD_MGR != 0
+            if (comp_ctx->enable_thread_mgr) {
+                if (!aot_gen_commit_sp_ip(comp_ctx->aot_frame,
+                                          comp_ctx->aot_frame->sp, frame_ip_br))
+                    return false;
+            }
+#endif
         }
         else {
             if (comp_ctx->aot_frame->sp > block_dst->frame_sp_max_reached)
@@ -1013,9 +1017,14 @@ aot_compile_conditional_br(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
             return false;
 
         if (block_dst->label_type == LABEL_TYPE_LOOP) {
-            if (!aot_gen_commit_sp_ip(comp_ctx->aot_frame,
-                                      comp_ctx->aot_frame->sp, frame_ip_br_if))
-                return false;
+#if WASM_ENABLE_THREAD_MGR != 0
+            if (comp_ctx->enable_thread_mgr) {
+                if (!aot_gen_commit_sp_ip(comp_ctx->aot_frame,
+                                          comp_ctx->aot_frame->sp,
+                                          frame_ip_br_if))
+                    return false;
+            }
+#endif
         }
         else {
             if (comp_ctx->aot_frame->sp > block_dst->frame_sp_max_reached)
@@ -1193,10 +1202,14 @@ aot_compile_op_br_table(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
             if (!aot_gen_commit_values(comp_ctx->aot_frame))
                 return false;
 
-            if (!aot_gen_commit_sp_ip(comp_ctx->aot_frame,
-                                      comp_ctx->aot_frame->sp,
-                                      frame_ip_br_table))
-                return false;
+#if WASM_ENABLE_THREAD_MGR != 0
+            if (comp_ctx->enable_thread_mgr) {
+                if (!aot_gen_commit_sp_ip(comp_ctx->aot_frame,
+                                          comp_ctx->aot_frame->sp,
+                                          frame_ip_br_table))
+                    return false;
+            }
+#endif
 
             for (i = 0; i <= br_count; i++) {
                 target_block = get_target_block(func_ctx, br_depths[i]);
@@ -1433,9 +1446,14 @@ commit_gc_and_check_suspend_flags(AOTCompContext *comp_ctx,
             return false;
 
         if (block_dst->label_type == LABEL_TYPE_LOOP) {
-            if (!aot_gen_commit_sp_ip(comp_ctx->aot_frame,
-                                      comp_ctx->aot_frame->sp, frame_ip_br_on))
-                return false;
+#if WASM_ENABLE_THREAD_MGR != 0
+            if (comp_ctx->enable_thread_mgr) {
+                if (!aot_gen_commit_sp_ip(comp_ctx->aot_frame,
+                                          comp_ctx->aot_frame->sp,
+                                          frame_ip_br_on))
+                    return false;
+            }
+#endif
         }
         else {
             if (comp_ctx->aot_frame->sp > block_dst->frame_sp_max_reached)

+ 536 - 25
core/iwasm/compilation/aot_emit_function.c

@@ -356,31 +356,550 @@ fail:
 }
 
 static bool
-call_aot_free_frame_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
+alloc_frame_for_aot_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+                         uint32 func_idx)
 {
-    LLVMValueRef param_values[1], ret_value, value, func;
-    LLVMTypeRef param_types[1], ret_type, func_type, func_ptr_type;
+    LLVMValueRef wasm_stack_top_bound = func_ctx->wasm_stack_top_bound;
+    LLVMValueRef wasm_stack_top_ptr = func_ctx->wasm_stack_top_ptr,
+                 wasm_stack_top;
+    LLVMValueRef wasm_stack_top_max, wasm_stack_top_new, offset, cmp;
+    LLVMValueRef cur_frame, new_frame, prev_frame_ptr;
+    LLVMValueRef cur_frame_ptr = func_ctx->cur_frame_ptr;
+    LLVMValueRef frame_sp, frame_sp_ptr, frame_ref, frame_ref_ptr;
+    LLVMValueRef func_idx_ptr, func_idx_val, func_inst_ptr, func_inst;
+    LLVMTypeRef int8_ptr_type;
+    LLVMBasicBlockRef check_wasm_stack_succ;
+    uint32 import_func_count = comp_ctx->comp_data->import_func_count;
+    uint32 param_cell_num = 0, local_cell_num = 0, i, j, k;
+    uint32 max_local_cell_num, max_stack_cell_num;
+    uint32 all_cell_num, frame_size, frame_size_with_outs_area;
+    uint32 aot_frame_ptr_num = offsetof(AOTFrame, lp) / sizeof(uintptr_t);
+    AOTImportFunc *import_funcs = comp_ctx->comp_data->import_funcs;
+    AOTFuncType *func_type;
+    AOTFunc *aot_func = NULL;
 
-    param_types[0] = comp_ctx->exec_env_type;
-    ret_type = INT8_TYPE;
+    /* Get param_cell_num, local_cell_num and max_stack_cell_num */
+    if (func_idx < import_func_count) {
+        func_type = import_funcs[func_idx].func_type;
+        for (i = 0; i < func_type->param_count; i++)
+            param_cell_num += wasm_value_type_cell_num_internal(
+                func_type->types[i], comp_ctx->pointer_size);
+        max_local_cell_num = param_cell_num > 2 ? param_cell_num : 2;
+        max_stack_cell_num = 0;
+    }
+    else {
+        aot_func = comp_ctx->comp_data->funcs[func_idx - import_func_count];
+        param_cell_num = aot_func->param_cell_num;
+        local_cell_num = aot_func->local_cell_num;
+        max_local_cell_num = param_cell_num + local_cell_num;
+        max_stack_cell_num = aot_func->max_stack_cell_num;
+    }
+
+    all_cell_num = max_local_cell_num + max_stack_cell_num;
+
+    /* Get size of the frame to allocate and get size with outs_area to
+       check whether wasm operand stack is overflow */
+    if (!comp_ctx->is_jit_mode) {
+        /* Refer to aot_alloc_frame */
+        if (!comp_ctx->enable_gc) {
+            frame_size =
+                comp_ctx->pointer_size * aot_frame_ptr_num + all_cell_num * 4;
+        }
+        else
+            frame_size = comp_ctx->pointer_size * aot_frame_ptr_num
+                         + align_uint(all_cell_num * 5, 4);
+        frame_size_with_outs_area = frame_size
+                                    + comp_ctx->pointer_size * aot_frame_ptr_num
+                                    + max_stack_cell_num * 4;
+    }
+    else {
+        /* Refer to wasm_interp_interp_frame_size */
+        if (!comp_ctx->enable_gc)
+            frame_size = offsetof(WASMInterpFrame, lp) + all_cell_num * 4;
+        else
+            frame_size =
+                offsetof(WASMInterpFrame, lp) + align_uint(all_cell_num * 5, 4);
+        frame_size_with_outs_area =
+            frame_size + offsetof(WASMInterpFrame, lp) + max_stack_cell_num * 4;
+    }
+
+    /* `int8 **` type */
+    int8_ptr_type = LLVMPointerType(INT8_PTR_TYPE, 0);
+    if (!int8_ptr_type) {
+        aot_set_last_error("create llvm pointer type failed");
+        return false;
+    }
 
-    if (comp_ctx->is_jit_mode)
-        GET_AOT_FUNCTION(llvm_jit_free_frame, 1);
-    else
-        GET_AOT_FUNCTION(aot_free_frame, 1);
+    /* Get exec_env->wasm_stack.top */
+    if (!(wasm_stack_top =
+              LLVMBuildLoad2(comp_ctx->builder, INT8_PTR_TYPE,
+                             wasm_stack_top_ptr, "wasm_stack_top"))) {
+        aot_set_last_error("load wasm_stack.top failed");
+        return false;
+    }
 
-    param_values[0] = func_ctx->exec_env;
+    cur_frame = func_ctx->cur_frame;
+    new_frame = wasm_stack_top;
 
-    if (!(ret_value = LLVMBuildCall2(comp_ctx->builder, func_type, func,
-                                     param_values, 1, "call_aot_free_frame"))) {
-        aot_set_last_error("llvm build call failed.");
+    /* Check whether wasm operand stack is overflow */
+    offset = I32_CONST(frame_size_with_outs_area);
+    CHECK_LLVM_CONST(offset);
+    if (!(wasm_stack_top_max = LLVMBuildInBoundsGEP2(
+              comp_ctx->builder, INT8_TYPE, wasm_stack_top, &offset, 1,
+              "wasm_stack_top_max"))) {
+        aot_set_last_error("llvm build in bounds gep failed");
         return false;
     }
 
+    if (!(check_wasm_stack_succ = LLVMAppendBasicBlockInContext(
+              comp_ctx->context, func_ctx->func, "check_wasm_stack_succ"))) {
+        aot_set_last_error("llvm add basic block failed.");
+        return false;
+    }
+
+    LLVMMoveBasicBlockAfter(check_wasm_stack_succ,
+                            LLVMGetInsertBlock(comp_ctx->builder));
+
+    if (!(cmp = LLVMBuildICmp(comp_ctx->builder, LLVMIntUGT, wasm_stack_top_max,
+                              wasm_stack_top_bound, "cmp"))) {
+        aot_set_last_error("llvm build icmp failed");
+        return false;
+    }
+
+    if (!(aot_emit_exception(comp_ctx, func_ctx, EXCE_OPERAND_STACK_OVERFLOW,
+                             true, cmp, check_wasm_stack_succ))) {
+        return false;
+    }
+
+    /* exec_env->wasm_stack.top += frame_size */
+    offset = I32_CONST(frame_size);
+    CHECK_LLVM_CONST(offset);
+    if (!(wasm_stack_top_new = LLVMBuildInBoundsGEP2(
+              comp_ctx->builder, INT8_TYPE, wasm_stack_top, &offset, 1,
+              "wasm_stack_top_new"))) {
+        aot_set_last_error("llvm build in bounds gep failed");
+        return false;
+    }
+    if (!LLVMBuildStore(comp_ctx->builder, wasm_stack_top_new,
+                        wasm_stack_top_ptr)) {
+        aot_set_last_error("llvm build store failed");
+        return false;
+    }
+
+    if (func_idx < import_func_count) {
+        /* Only need to initialize new_frame->sp when it's import function
+           otherwise they will be committed in AOT code if needed */
+
+        /* new_frame->sp = new_frame->lp + max_local_cell_num */
+        if (!comp_ctx->is_jit_mode)
+            offset = I32_CONST(comp_ctx->pointer_size * 5);
+        else
+            offset = I32_CONST(offsetof(WASMInterpFrame, sp));
+        CHECK_LLVM_CONST(offset);
+        if (!(frame_sp_ptr =
+                  LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE, new_frame,
+                                        &offset, 1, "frame_sp_addr"))
+            || !(frame_sp_ptr =
+                     LLVMBuildBitCast(comp_ctx->builder, frame_sp_ptr,
+                                      int8_ptr_type, "frame_sp_ptr"))) {
+            aot_set_last_error("llvm get frame_sp_ptr failed");
+            return false;
+        }
+
+        if (!comp_ctx->is_jit_mode)
+            offset = I32_CONST(comp_ctx->pointer_size * aot_frame_ptr_num
+                               + max_local_cell_num * sizeof(uint32));
+        else
+            offset = I32_CONST(offsetof(WASMInterpFrame, lp)
+                               + max_local_cell_num * sizeof(uint32));
+        CHECK_LLVM_CONST(offset);
+        if (!(frame_sp =
+                  LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE, new_frame,
+                                        &offset, 1, "frame_sp"))) {
+            aot_set_last_error("llvm build in bounds gep failed");
+            return false;
+        }
+        if (!LLVMBuildStore(comp_ctx->builder, frame_sp, frame_sp_ptr)) {
+            aot_set_last_error("llvm build store failed");
+            return false;
+        }
+    }
+
+#if WASM_ENABLE_GC != 0
+    if (comp_ctx->enable_gc) {
+        if (!comp_ctx->is_jit_mode) {
+            /* new_frame->frame_ref = new_frame->lp + max_local_cell_num
+                                      + max_stack_cell_num */
+            offset = I32_CONST(comp_ctx->pointer_size * 6);
+            CHECK_LLVM_CONST(offset);
+            if (!(frame_ref_ptr = LLVMBuildInBoundsGEP2(
+                      comp_ctx->builder, INT8_TYPE, new_frame, &offset, 1,
+                      "frame_ref_addr"))
+                || !(frame_ref_ptr =
+                         LLVMBuildBitCast(comp_ctx->builder, frame_ref_ptr,
+                                          int8_ptr_type, "frame_ref_ptr"))) {
+                aot_set_last_error("llvm get frame_ref_ptr failed");
+                return false;
+            }
+
+            offset = I32_CONST(comp_ctx->pointer_size * aot_frame_ptr_num
+                               + (max_local_cell_num + max_stack_cell_num)
+                                     * sizeof(uint32));
+            CHECK_LLVM_CONST(offset);
+            if (!(frame_ref = LLVMBuildInBoundsGEP2(comp_ctx->builder,
+                                                    INT8_TYPE, new_frame,
+                                                    &offset, 1, "frame_ref"))) {
+                aot_set_last_error("llvm build in bounds gep failed");
+                return false;
+            }
+            if (!LLVMBuildStore(comp_ctx->builder, frame_ref, frame_ref_ptr)) {
+                aot_set_last_error("llvm build store failed");
+                return false;
+            }
+        }
+        else {
+            /* Get frame_ref in WASMInterpFrame */
+            offset = I32_CONST(offsetof(WASMInterpFrame, lp)
+                               + (max_local_cell_num + max_stack_cell_num)
+                                     * sizeof(uint32));
+            CHECK_LLVM_CONST(offset);
+            if (!(frame_ref = LLVMBuildInBoundsGEP2(comp_ctx->builder,
+                                                    INT8_TYPE, new_frame,
+                                                    &offset, 1, "frame_ref"))) {
+                aot_set_last_error("llvm build in bounds gep failed");
+                return false;
+            }
+        }
+
+        /* Initialize frame ref flags for import function */
+        if (func_idx < import_func_count) {
+            func_type = import_funcs[func_idx].func_type;
+            for (i = 0, j = 0; i < func_type->param_count; i++) {
+                if (aot_is_type_gc_reftype(func_type->types[i])
+                    && !wasm_is_reftype_i31ref(func_type->types[i])) {
+                    for (k = 0; k < comp_ctx->pointer_size / sizeof(uint32);
+                         k++) {
+                        /* frame_ref[j++] = 1 */
+                        offset = I32_CONST(j);
+                        CHECK_LLVM_CONST(offset);
+                        frame_ref_ptr = LLVMBuildInBoundsGEP2(
+                            comp_ctx->builder, INT8_TYPE, frame_ref, &offset, 1,
+                            "frame_ref_ptr");
+                        if (!LLVMBuildStore(comp_ctx->builder, I8_ONE,
+                                            frame_ref_ptr)) {
+                            aot_set_last_error("llvm build store failed");
+                            return false;
+                        }
+                        j++;
+                    }
+                }
+                else {
+                    uint32 value_type_cell_num =
+                        wasm_value_type_cell_num_internal(
+                            func_type->types[i], comp_ctx->pointer_size);
+                    for (k = 0; k < value_type_cell_num; k++) {
+                        /* frame_ref[j++] = 0 */
+                        offset = I32_CONST(j);
+                        CHECK_LLVM_CONST(offset);
+                        frame_ref_ptr = LLVMBuildInBoundsGEP2(
+                            comp_ctx->builder, INT8_TYPE, frame_ref, &offset, 1,
+                            "frame_ref_ptr");
+                        if (!LLVMBuildStore(comp_ctx->builder, I8_ZERO,
+                                            frame_ref_ptr)) {
+                            aot_set_last_error("llvm build store failed");
+                            return false;
+                        }
+                        j++;
+                    }
+                }
+            }
+
+            for (; j < 2; j++) {
+                /* frame_ref[j++] = 0 */
+                offset = I32_CONST(j);
+                CHECK_LLVM_CONST(offset);
+                frame_ref_ptr = LLVMBuildInBoundsGEP2(
+                    comp_ctx->builder, INT8_TYPE, frame_ref, &offset, 1,
+                    "frame_ref_ptr");
+                if (!LLVMBuildStore(comp_ctx->builder, I8_ZERO,
+                                    frame_ref_ptr)) {
+                    aot_set_last_error("llvm build store failed");
+                    return false;
+                }
+            }
+        }
+    }
+#endif /* end of WASM_ENABLE_GC != 0 */
+
+    /* new_frame->prev_frame = cur_frame */
+    if (!(prev_frame_ptr = LLVMBuildBitCast(comp_ctx->builder, new_frame,
+                                            int8_ptr_type, "prev_frame_ptr"))) {
+        aot_set_last_error("llvm build bitcast failed");
+        return false;
+    }
+    if (!LLVMBuildStore(comp_ctx->builder, cur_frame, prev_frame_ptr)) {
+        aot_set_last_error("llvm build store failed");
+        return false;
+    }
+
+    if (!comp_ctx->is_jit_mode) {
+        /* aot mode: new_frame->func_idx = func_idx */
+        func_idx_val = comp_ctx->pointer_size == sizeof(uint64)
+                           ? I64_CONST(func_idx)
+                           : I32_CONST(func_idx);
+        offset = I32_CONST(comp_ctx->pointer_size);
+        CHECK_LLVM_CONST(func_idx_val);
+        CHECK_LLVM_CONST(offset);
+        if (!(func_idx_ptr =
+                  LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE, new_frame,
+                                        &offset, 1, "func_idx_addr"))
+            || !(func_idx_ptr =
+                     LLVMBuildBitCast(comp_ctx->builder, func_idx_ptr,
+                                      INTPTR_T_PTR_TYPE, "func_idx_ptr"))) {
+            aot_set_last_error("llvm get func_idx_ptr failed");
+            return false;
+        }
+        if (!LLVMBuildStore(comp_ctx->builder, func_idx_val, func_idx_ptr)) {
+            aot_set_last_error("llvm build store failed");
+            return false;
+        }
+    }
+    else {
+        /* jit mode: frame->function = module_inst->e->functions + func_index */
+        LLVMValueRef functions;
+        uint32 offset_functions =
+            get_module_inst_extra_offset(comp_ctx)
+            + offsetof(WASMModuleInstanceExtra, functions);
+
+        offset = I32_CONST(offset_functions);
+        CHECK_LLVM_CONST(offset);
+        if (!(functions = LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE,
+                                                func_ctx->aot_inst, &offset, 1,
+                                                "functions_addr"))) {
+            aot_set_last_error("llvm build inbounds gep failed");
+            return false;
+        }
+
+        if (!(functions = LLVMBuildBitCast(comp_ctx->builder, functions,
+                                           int8_ptr_type, "functions_ptr"))) {
+            aot_set_last_error("llvm build bitcast failed");
+            return false;
+        }
+
+        if (!(functions = LLVMBuildLoad2(comp_ctx->builder, INT8_PTR_TYPE,
+                                         functions, "functions"))) {
+            aot_set_last_error("llvm build load failed");
+            return false;
+        }
+
+        offset = I32_CONST(sizeof(WASMFunctionInstance) * func_idx);
+        CHECK_LLVM_CONST(offset);
+        if (!(func_inst =
+                  LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE, functions,
+                                        &offset, 1, "func_inst"))) {
+            aot_set_last_error("llvm build inbounds gep failed");
+            return false;
+        }
+
+        offset = I32_CONST(offsetof(WASMInterpFrame, function));
+        CHECK_LLVM_CONST(offset);
+        if (!(func_inst_ptr =
+                  LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE, new_frame,
+                                        &offset, 1, "func_inst_addr"))
+            || !(func_inst_ptr =
+                     LLVMBuildBitCast(comp_ctx->builder, func_inst_ptr,
+                                      int8_ptr_type, "func_inst_ptr"))) {
+            aot_set_last_error("llvm get func_inst_ptr failed");
+            return false;
+        }
+
+        if (!LLVMBuildStore(comp_ctx->builder, func_inst, func_inst_ptr)) {
+            aot_set_last_error("llvm build store failed");
+            return false;
+        }
+    }
+
+    /* No need to initialize new_frame->sp and new_frame->ip_offset
+       since they will be committed in AOT code if needed */
+
+    /* exec_env->cur_frame = new_frame */
+    if (!LLVMBuildStore(comp_ctx->builder, new_frame, cur_frame_ptr)) {
+        aot_set_last_error("llvm build store failed");
+        return false;
+    }
+
+    if (comp_ctx->enable_perf_profiling || comp_ctx->enable_memory_profiling) {
+        LLVMTypeRef param_types[2], func_type, func_ptr_type;
+        LLVMValueRef param_values[2], func, res;
+        char *func_name = "aot_frame_update_profile_info";
+
+        /* Call aot_frame_update_profile_info for AOT or
+           llvm_jit_frame_update_profile_info for JIT */
+
+        param_types[0] = comp_ctx->exec_env_type;
+        param_types[1] = INT8_TYPE;
+
+        if (!(func_type = LLVMFunctionType(VOID_TYPE, param_types, 2, false))) {
+            aot_set_last_error("llvm add function type failed.");
+            return false;
+        }
+
+        if (comp_ctx->is_jit_mode) {
+            if (!(func_ptr_type = LLVMPointerType(func_type, 0))) {
+                aot_set_last_error("create LLVM function type failed.");
+                return false;
+            }
+
+            /* JIT mode, call the function directly */
+            if (!(func = I64_CONST(
+                      (uint64)(uintptr_t)llvm_jit_frame_update_profile_info))
+                || !(func = LLVMConstIntToPtr(func, func_ptr_type))) {
+                aot_set_last_error("create LLVM value failed.");
+                return false;
+            }
+        }
+        else if (comp_ctx->is_indirect_mode) {
+            int32 func_index;
+            if (!(func_ptr_type = LLVMPointerType(func_type, 0))) {
+                aot_set_last_error("create LLVM function type failed.");
+                return false;
+            }
+            func_index = aot_get_native_symbol_index(comp_ctx, func_name);
+            if (func_index < 0) {
+                return false;
+            }
+            if (!(func =
+                      aot_get_func_from_table(comp_ctx, func_ctx->native_symbol,
+                                              func_ptr_type, func_index))) {
+                return false;
+            }
+        }
+        else {
+            if (!(func = LLVMGetNamedFunction(func_ctx->module, func_name))
+                && !(func = LLVMAddFunction(func_ctx->module, func_name,
+                                            func_type))) {
+                aot_set_last_error("add LLVM function failed.");
+                return false;
+            }
+        }
+
+        param_values[0] = func_ctx->exec_env;
+        param_values[1] = I8_ONE;
+
+        if (!(res = LLVMBuildCall2(comp_ctx->builder, func_type, func,
+                                   param_values, 2, ""))) {
+            aot_set_last_error("llvm build call failed.");
+            return false;
+        }
+    }
+
     return true;
 fail:
+
     return false;
 }
+
+static bool
+free_frame_for_aot_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
+{
+    LLVMValueRef cur_frame_ptr = func_ctx->cur_frame_ptr, cur_frame;
+    LLVMValueRef wasm_stack_top_ptr = func_ctx->wasm_stack_top_ptr;
+    LLVMTypeRef int8_ptr_type;
+
+    /* `int8 **` type */
+    int8_ptr_type = LLVMPointerType(INT8_PTR_TYPE, 0);
+    if (!int8_ptr_type) {
+        aot_set_last_error("create llvm pointer type failed");
+        return false;
+    }
+
+    if (comp_ctx->enable_perf_profiling) {
+        LLVMTypeRef param_types[2], func_type, func_ptr_type;
+        LLVMValueRef param_values[2], func, res;
+        char *func_name = "aot_frame_update_profile_info";
+
+        /* call aot_frame_update_profile_info for AOT or
+           llvm_jit_frame_update_profile_info for JIT */
+
+        param_types[0] = comp_ctx->exec_env_type;
+        param_types[1] = INT8_TYPE;
+
+        if (!(func_type = LLVMFunctionType(VOID_TYPE, param_types, 2, false))) {
+            aot_set_last_error("llvm add function type failed.");
+            return false;
+        }
+
+        if (comp_ctx->is_jit_mode) {
+            if (!(func_ptr_type = LLVMPointerType(func_type, 0))) {
+                aot_set_last_error("create LLVM function type failed.");
+                return false;
+            }
+
+            /* JIT mode, call the function directly */
+            if (!(func = I64_CONST(
+                      (uint64)(uintptr_t)llvm_jit_frame_update_profile_info))
+                || !(func = LLVMConstIntToPtr(func, func_ptr_type))) {
+                aot_set_last_error("create LLVM value failed.");
+                return false;
+            }
+        }
+        else if (comp_ctx->is_indirect_mode) {
+            int32 func_index;
+            if (!(func_ptr_type = LLVMPointerType(func_type, 0))) {
+                aot_set_last_error("create LLVM function type failed.");
+                return false;
+            }
+            func_index = aot_get_native_symbol_index(comp_ctx, func_name);
+            if (func_index < 0) {
+                return false;
+            }
+            if (!(func =
+                      aot_get_func_from_table(comp_ctx, func_ctx->native_symbol,
+                                              func_ptr_type, func_index))) {
+                return false;
+            }
+        }
+        else {
+            if (!(func = LLVMGetNamedFunction(func_ctx->module, func_name))
+                && !(func = LLVMAddFunction(func_ctx->module, func_name,
+                                            func_type))) {
+                aot_set_last_error("add LLVM function failed.");
+                return false;
+            }
+        }
+
+        param_values[0] = func_ctx->exec_env;
+        param_values[1] = I8_ZERO;
+
+        if (!(res = LLVMBuildCall2(comp_ctx->builder, func_type, func,
+                                   param_values, 2, ""))) {
+            aot_set_last_error("llvm build call failed.");
+            return false;
+        }
+    }
+
+    /* cur_frame = exec_env->cur_frame */
+    if (!(cur_frame = LLVMBuildLoad2(comp_ctx->builder, INT8_PTR_TYPE,
+                                     cur_frame_ptr, "cur_frame"))) {
+        aot_set_last_error("llvm build load failed");
+        return false;
+    }
+
+    /* exec_env->wasm_stack.top = cur_frame */
+    if (!LLVMBuildStore(comp_ctx->builder, cur_frame, wasm_stack_top_ptr)) {
+        aot_set_last_error("llvm build store failed");
+        return false;
+    }
+
+    /* exec_env->cur_frame = prev_frame */
+    if (!LLVMBuildStore(comp_ctx->builder, func_ctx->cur_frame,
+                        cur_frame_ptr)) {
+        aot_set_last_error("llvm build store failed");
+        return false;
+    }
+
+    return true;
+}
 #endif /* end of (WASM_ENABLE_DUMP_CALL_STACK != 0) \
                  || (WASM_ENABLE_PERF_PROFILING != 0) */
 
@@ -678,15 +1197,7 @@ aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
 
 #if (WASM_ENABLE_DUMP_CALL_STACK != 0) || (WASM_ENABLE_PERF_PROFILING != 0)
     if (comp_ctx->enable_aux_stack_frame) {
-        LLVMValueRef func_idx_const;
-
-        if (!(func_idx_const = I32_CONST(func_idx))) {
-            aot_set_last_error("llvm build const failed.");
-            return false;
-        }
-        /*  TODO: use current frame instead of allocating new frame
-                  for WASM_OP_RETURN_CALL */
-        if (!call_aot_alloc_frame_func(comp_ctx, func_ctx, func_idx_const))
+        if (!alloc_frame_for_aot_func(comp_ctx, func_ctx, func_idx))
             return false;
     }
 #endif
@@ -1012,7 +1523,7 @@ aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
 
 #if (WASM_ENABLE_DUMP_CALL_STACK != 0) || (WASM_ENABLE_PERF_PROFILING != 0)
     if (comp_ctx->enable_aux_stack_frame) {
-        if (!call_aot_free_frame_func(comp_ctx, func_ctx))
+        if (!free_frame_for_aot_func(comp_ctx, func_ctx))
             goto fail;
     }
 #endif
@@ -1766,7 +2277,7 @@ aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
 
 #if (WASM_ENABLE_DUMP_CALL_STACK != 0) || (WASM_ENABLE_PERF_PROFILING != 0)
     if (comp_ctx->enable_aux_stack_frame) {
-        if (!call_aot_free_frame_func(comp_ctx, func_ctx))
+        if (!free_frame_for_aot_func(comp_ctx, func_ctx))
             goto fail;
     }
 #endif
@@ -2274,7 +2785,7 @@ aot_compile_op_call_ref(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
 
 #if (WASM_ENABLE_DUMP_CALL_STACK != 0) || (WASM_ENABLE_PERF_PROFILING != 0)
     if (comp_ctx->enable_aux_stack_frame) {
-        if (!call_aot_free_frame_func(comp_ctx, func_ctx))
+        if (!free_frame_for_aot_func(comp_ctx, func_ctx))
             goto fail;
     }
 #endif

+ 12 - 0
core/iwasm/compilation/aot_emit_table.c

@@ -52,6 +52,18 @@ get_tbl_inst_offset(const AOTCompContext *comp_ctx,
     return offset;
 }
 
+uint32
+get_module_inst_extra_offset(AOTCompContext *comp_ctx)
+{
+    const AOTCompData *comp_data = comp_ctx->comp_data;
+    uint32 table_count = comp_data->import_table_count + comp_data->table_count;
+    uint64 offset = get_tbl_inst_offset(comp_ctx, NULL, table_count);
+    uint32 offset_32 = (uint32)offset;
+    bh_assert(offset <= UINT32_MAX);
+    offset_32 = align_uint(offset_32, 8);
+    return offset_32;
+}
+
 #if WASM_ENABLE_REF_TYPES != 0 || WASM_ENABLE_GC != 0
 
 LLVMValueRef

+ 4 - 1
core/iwasm/compilation/aot_emit_table.h

@@ -49,6 +49,9 @@ uint64
 get_tbl_inst_offset(const AOTCompContext *comp_ctx,
                     const AOTFuncContext *func_ctx, uint32 tbl_idx);
 
+uint32
+get_module_inst_extra_offset(AOTCompContext *comp_ctx);
+
 LLVMValueRef
 aot_compile_get_tbl_inst(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
                          uint32 tbl_idx);
@@ -56,4 +59,4 @@ aot_compile_get_tbl_inst(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
 #ifdef __cplusplus
 } /* end of extern "C" */
 #endif
-#endif
+#endif

+ 37 - 18
core/iwasm/compilation/aot_llvm.c

@@ -274,18 +274,6 @@ aot_estimate_stack_usage_for_function_call(const AOTCompContext *comp_ctx,
     return size;
 }
 
-static uint32
-get_inst_extra_offset(AOTCompContext *comp_ctx)
-{
-    const AOTCompData *comp_data = comp_ctx->comp_data;
-    uint32 table_count = comp_data->import_table_count + comp_data->table_count;
-    uint64 offset = get_tbl_inst_offset(comp_ctx, NULL, table_count);
-    uint32 offset_32 = (uint32)offset;
-    bh_assert(offset <= UINT32_MAX);
-    offset_32 = align_uint((uint32)offset_32, 8);
-    return offset_32;
-}
-
 /*
  * a "precheck" function performs a few things before calling wrapped_func.
  *
@@ -389,7 +377,7 @@ aot_add_precheck_function(AOTCompContext *comp_ctx, LLVMModuleRef module,
         LLVMValueRef offset;
         LLVMValueRef stack_sizes_p;
 
-        offset_u32 = get_inst_extra_offset(comp_ctx);
+        offset_u32 = get_module_inst_extra_offset(comp_ctx);
         offset_u32 += offsetof(AOTModuleInstanceExtra, stack_sizes);
         offset = I32_CONST(offset_u32);
         if (!offset) {
@@ -1012,21 +1000,43 @@ create_aux_stack_info(const AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
 static bool
 create_aux_stack_frame(const AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
 {
-    LLVMValueRef offset = I32_ONE, cur_frame_addr;
+    LLVMValueRef wasm_stack_top_bound_ptr, offset;
 
-    if (!(cur_frame_addr = LLVMBuildInBoundsGEP2(
+    offset = I32_ONE;
+    if (!(func_ctx->cur_frame_ptr = LLVMBuildInBoundsGEP2(
               comp_ctx->builder, OPQ_PTR_TYPE, func_ctx->exec_env, &offset, 1,
-              "cur_frame_addr"))) {
+              "cur_frame_ptr"))) {
         aot_set_last_error("llvm build in bounds gep failed");
         return false;
     }
 
-    if (!(func_ctx->cur_frame = LLVMBuildLoad2(comp_ctx->builder, OPQ_PTR_TYPE,
-                                               cur_frame_addr, "cur_frame"))) {
+    if (!(func_ctx->cur_frame =
+              LLVMBuildLoad2(comp_ctx->builder, OPQ_PTR_TYPE,
+                             func_ctx->cur_frame_ptr, "cur_frame"))) {
         aot_set_last_error("llvm build load failed");
         return false;
     }
 
+    /* Get exec_env->wasm_stack.top_boundary and its address */
+    offset = I32_TEN;
+    if (!(wasm_stack_top_bound_ptr = LLVMBuildInBoundsGEP2(
+              comp_ctx->builder, OPQ_PTR_TYPE, func_ctx->exec_env, &offset, 1,
+              "wasm_stack_top_bound_ptr"))
+        || !(func_ctx->wasm_stack_top_bound = LLVMBuildLoad2(
+                 comp_ctx->builder, INT8_PTR_TYPE, wasm_stack_top_bound_ptr,
+                 "wasm_stack_top_bound"))) {
+        aot_set_last_error("load wasm_stack.top_boundary failed");
+        return false;
+    }
+
+    offset = I32_ELEVEN;
+    if (!(func_ctx->wasm_stack_top_ptr = LLVMBuildInBoundsGEP2(
+              comp_ctx->builder, OPQ_PTR_TYPE, func_ctx->exec_env, &offset, 1,
+              "wasm_stack_top_ptr"))) {
+        aot_set_last_error("llvm build inbounds gep failed");
+        return false;
+    }
+
     return true;
 }
 
@@ -1945,6 +1955,9 @@ aot_create_llvm_consts(AOTLLVMConsts *consts, AOTCompContext *comp_ctx)
     if (!(consts->i8_zero = I8_CONST(0)))
         return false;
 
+    if (!(consts->i8_one = I8_CONST(1)))
+        return false;
+
     if (!(consts->f32_zero = F32_CONST(0)))
         return false;
 
@@ -2530,6 +2543,12 @@ aot_create_comp_context(const AOTCompData *comp_data, aot_comp_option_t option)
     if (option->enable_aux_stack_frame)
         comp_ctx->enable_aux_stack_frame = true;
 
+    if (option->enable_perf_profiling)
+        comp_ctx->enable_perf_profiling = true;
+
+    if (option->enable_memory_profiling)
+        comp_ctx->enable_memory_profiling = true;
+
     if (option->enable_aux_stack_check)
         comp_ctx->enable_aux_stack_check = true;
 

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

@@ -126,6 +126,9 @@ typedef struct AOTCompFrame {
     /* Max operand stack slot number */
     uint32 max_stack_cell_num;
 
+    /* Size of current AOTFrame/WASMInterpFrame */
+    uint32 cur_frame_size;
+
     /* Stack top pointer */
     AOTValueSlot *sp;
 
@@ -230,6 +233,9 @@ typedef struct AOTFuncContext {
     LLVMValueRef cur_exception;
 
     LLVMValueRef cur_frame;
+    LLVMValueRef cur_frame_ptr;
+    LLVMValueRef wasm_stack_top_bound;
+    LLVMValueRef wasm_stack_top_ptr;
 
     bool mem_space_unchanged;
     AOTCheckedAddrList checked_addr_list;
@@ -298,6 +304,7 @@ typedef struct AOTLLVMConsts {
     LLVMValueRef i1_zero;
     LLVMValueRef i1_one;
     LLVMValueRef i8_zero;
+    LLVMValueRef i8_one;
     LLVMValueRef i32_zero;
     LLVMValueRef i64_zero;
     LLVMValueRef f32_zero;
@@ -400,6 +407,12 @@ typedef struct AOTCompContext {
     /* Generate auxiliary stack frame */
     bool enable_aux_stack_frame;
 
+    /* Function performance profiling */
+    bool enable_perf_profiling;
+
+    /* Memory usage profiling */
+    bool enable_memory_profiling;
+
     /* Thread Manager */
     bool enable_thread_mgr;
 

+ 7 - 7
core/iwasm/fast-jit/cg/x86-64/jit_codegen_x86_64.cpp

@@ -8456,7 +8456,7 @@ jit_codegen_compile_call_to_llvm_jit(const WASMType *func_type)
     /* r10 = outs_area->lp */
     {
         x86::Mem m(regs_i64[hreg_info->exec_env_hreg_index],
-                   (uint32)offsetof(WASMExecEnv, wasm_stack.s.top));
+                   (uint32)offsetof(WASMExecEnv, wasm_stack.top));
         a.mov(reg_lp, m);
         a.add(reg_lp, (uint32)offsetof(WASMInterpFrame, lp));
     }
@@ -8696,15 +8696,15 @@ fast_jit_alloc_frame(WASMExecEnv *exec_env, uint32 param_cell_num,
      * frame to store the function results from jit function to call,
      * the second is the frame for the jit function
      */
-    if ((uint8 *)exec_env->wasm_stack.s.top + size_frame1 + size_frame2
-        > exec_env->wasm_stack.s.top_boundary) {
+    if ((uint8 *)exec_env->wasm_stack.top + size_frame1 + size_frame2
+        > exec_env->wasm_stack.top_boundary) {
         wasm_set_exception(module_inst, "wasm operand stack overflow");
         return NULL;
     }
 
     /* Allocate the frame */
-    frame = (WASMInterpFrame *)exec_env->wasm_stack.s.top;
-    exec_env->wasm_stack.s.top += size_frame1;
+    frame = (WASMInterpFrame *)exec_env->wasm_stack.top;
+    exec_env->wasm_stack.top += size_frame1;
 
     frame->function = NULL;
     frame->ip = NULL;
@@ -9068,9 +9068,9 @@ jit_codegen_compile_call_to_fast_jit(const WASMModule *module, uint32 func_idx)
     /* rdx = exec_env->cur_frame->prev_frame */
     a.mov(x86::rdx,
           x86::ptr(x86::rsi, (uint32)offsetof(WASMInterpFrame, prev_frame)));
-    /* exec_env->wasm_stack.s.top = cur_frame */
+    /* exec_env->wasm_stack.top = cur_frame */
     {
-        x86::Mem m(x86::rdi, offsetof(WASMExecEnv, wasm_stack.s.top));
+        x86::Mem m(x86::rdi, offsetof(WASMExecEnv, wasm_stack.top));
         a.mov(m, x86::rsi);
     }
     /* exec_env->cur_frame = prev_frame */

+ 2 - 2
core/iwasm/fast-jit/fe/jit_emit_control.c

@@ -450,9 +450,9 @@ handle_func_return(JitCompContext *cc, JitBlock *block)
     }
 
     /* Free stack space of the current frame:
-       exec_env->wasm_stack.s.top = cur_frame */
+       exec_env->wasm_stack.top = cur_frame */
     GEN_INSN(STPTR, cc->fp_reg, cc->exec_env_reg,
-             NEW_CONST(I32, offsetof(WASMExecEnv, wasm_stack.s.top)));
+             NEW_CONST(I32, offsetof(WASMExecEnv, wasm_stack.top)));
     /* Set the prev_frame as the current frame:
        exec_env->cur_frame = prev_frame */
     GEN_INSN(STPTR, prev_frame, cc->exec_env_reg,

+ 6 - 6
core/iwasm/fast-jit/jit_frontend.c

@@ -891,12 +891,12 @@ init_func_translation(JitCompContext *cc)
 #endif
 #endif
 
-    /* top = exec_env->wasm_stack.s.top */
+    /* top = exec_env->wasm_stack.top */
     GEN_INSN(LDPTR, top, cc->exec_env_reg,
-             NEW_CONST(I32, offsetof(WASMExecEnv, wasm_stack.s.top)));
-    /* top_boundary = exec_env->wasm_stack.s.top_boundary */
+             NEW_CONST(I32, offsetof(WASMExecEnv, wasm_stack.top)));
+    /* top_boundary = exec_env->wasm_stack.top_boundary */
     GEN_INSN(LDPTR, top_boundary, cc->exec_env_reg,
-             NEW_CONST(I32, offsetof(WASMExecEnv, wasm_stack.s.top_boundary)));
+             NEW_CONST(I32, offsetof(WASMExecEnv, wasm_stack.top_boundary)));
     /* frame_boundary = top + frame_size + outs_size */
     GEN_INSN(ADD, frame_boundary, top, NEW_CONST(PTR, frame_size + outs_size));
     /* if frame_boundary > top_boundary, throw stack overflow exception */
@@ -909,9 +909,9 @@ init_func_translation(JitCompContext *cc)
     /* Add first and then sub to reduce one used register */
     /* new_top = frame_boundary - outs_size = top + frame_size */
     GEN_INSN(SUB, new_top, frame_boundary, NEW_CONST(PTR, outs_size));
-    /* exec_env->wasm_stack.s.top = new_top */
+    /* exec_env->wasm_stack.top = new_top */
     GEN_INSN(STPTR, new_top, cc->exec_env_reg,
-             NEW_CONST(I32, offsetof(WASMExecEnv, wasm_stack.s.top)));
+             NEW_CONST(I32, offsetof(WASMExecEnv, wasm_stack.top)));
     /* frame_sp = frame->lp + local_size */
     GEN_INSN(ADD, frame_sp, top,
              NEW_CONST(PTR, offsetof(WASMInterpFrame, lp) + local_size));

+ 2 - 0
core/iwasm/include/aot_comp_option.h

@@ -21,6 +21,8 @@ typedef struct AOTCompOption {
     bool enable_ref_types;
     bool enable_aux_stack_check;
     bool enable_aux_stack_frame;
+    bool enable_perf_profiling;
+    bool enable_memory_profiling;
     bool disable_llvm_intrinsics;
     bool disable_llvm_lto;
     bool enable_llvm_pgo;

+ 1 - 1
core/iwasm/interpreter/wasm_interp_classic.c

@@ -6196,7 +6196,7 @@ wasm_interp_call_wasm(WASMModuleInstance *module_inst, WASMExecEnv *exec_env,
     frame->sp = frame->lp + 0;
 
     if ((uint8 *)(outs_area->lp + function->param_cell_num)
-        > exec_env->wasm_stack.s.top_boundary) {
+        > exec_env->wasm_stack.top_boundary) {
         wasm_set_exception(module_inst, "wasm operand stack overflow");
         return;
     }

+ 2 - 2
core/iwasm/interpreter/wasm_interp_fast.c

@@ -5771,7 +5771,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
         }
 
         if ((uint8 *)(outs_area->lp + cur_func->param_cell_num)
-            > exec_env->wasm_stack.s.top_boundary) {
+            > exec_env->wasm_stack.top_boundary) {
             wasm_set_exception(module, "wasm operand stack overflow");
             goto got_exception;
         }
@@ -6069,7 +6069,7 @@ wasm_interp_call_wasm(WASMModuleInstance *module_inst, WASMExecEnv *exec_env,
     frame->ret_offset = 0;
 
     if ((uint8 *)(outs_area->operand + function->const_cell_num + argc)
-        > exec_env->wasm_stack.s.top_boundary) {
+        > exec_env->wasm_stack.top_boundary) {
         wasm_set_exception((WASMModuleInstance *)exec_env->module_inst,
                            "wasm operand stack overflow");
         return;

+ 6 - 2
core/iwasm/interpreter/wasm_loader.c

@@ -4854,11 +4854,15 @@ init_llvm_jit_functions_stage1(WASMModule *module, char *error_buf,
     option.enable_gc = true;
 #endif
     option.enable_aux_stack_check = true;
-#if (WASM_ENABLE_PERF_PROFILING != 0) || (WASM_ENABLE_DUMP_CALL_STACK != 0) \
-    || (WASM_ENABLE_JIT_STACK_FRAME != 0)
+#if WASM_ENABLE_PERF_PROFILING != 0 || WASM_ENABLE_DUMP_CALL_STACK != 0 \
+    || WASM_ENABLE_JIT_STACK_FRAME != 0
     option.enable_aux_stack_frame = true;
 #endif
+#if WASM_ENABLE_PERF_PROFILING != 0
+    option.enable_perf_profiling = true;
+#endif
 #if WASM_ENABLE_MEMORY_PROFILING != 0
+    option.enable_memory_profiling = true;
     option.enable_stack_estimation = true;
 #endif
 

+ 6 - 2
core/iwasm/interpreter/wasm_mini_loader.c

@@ -2137,11 +2137,15 @@ init_llvm_jit_functions_stage1(WASMModule *module, char *error_buf,
     option.enable_ref_types = true;
 #endif
     option.enable_aux_stack_check = true;
-#if (WASM_ENABLE_PERF_PROFILING != 0) || (WASM_ENABLE_DUMP_CALL_STACK != 0) \
-    || (WASM_ENABLE_JIT_STACK_FRAME != 0)
+#if WASM_ENABLE_PERF_PROFILING != 0 || WASM_ENABLE_DUMP_CALL_STACK != 0 \
+    || WASM_ENABLE_JIT_STACK_FRAME != 0
     option.enable_aux_stack_frame = true;
 #endif
+#if WASM_ENABLE_PERF_PROFILING != 0
+    option.enable_perf_profiling = true;
+#endif
 #if WASM_ENABLE_MEMORY_PROFILING != 0
+    option.enable_memory_profiling = true;
     option.enable_stack_estimation = true;
 #endif
 

+ 30 - 2
core/iwasm/interpreter/wasm_runtime.c

@@ -2930,7 +2930,7 @@ call_wasm_with_hw_bound_check(WASMModuleInstance *module_inst,
     uint32 page_size = os_getpagesize();
     uint32 guard_page_count = STACK_OVERFLOW_CHECK_GUARD_PAGE_COUNT;
     WASMRuntimeFrame *prev_frame = wasm_exec_env_get_cur_frame(exec_env);
-    uint8 *prev_top = exec_env->wasm_stack.s.top;
+    uint8 *prev_top = exec_env->wasm_stack.top;
 #ifdef BH_PLATFORM_WINDOWS
     int result;
     bool has_exception;
@@ -2998,7 +2998,7 @@ call_wasm_with_hw_bound_check(WASMModuleInstance *module_inst,
 #endif
         /* Restore operand frames */
         wasm_exec_env_set_cur_frame(exec_env, prev_frame);
-        exec_env->wasm_stack.s.top = prev_top;
+        exec_env->wasm_stack.top = prev_top;
     }
 
     jmpbuf_node_pop = wasm_exec_env_pop_jmpbuf(exec_env);
@@ -4209,6 +4209,34 @@ llvm_jit_free_frame(WASMExecEnv *exec_env)
     wasm_exec_env_free_wasm_frame(exec_env, frame);
     wasm_exec_env_set_cur_frame(exec_env, prev_frame);
 }
+
+void
+llvm_jit_frame_update_profile_info(WASMExecEnv *exec_env, bool alloc_frame)
+{
+#if WASM_ENABLE_PERF_PROFILING != 0
+    WASMInterpFrame *cur_frame = exec_env->cur_frame;
+
+    if (alloc_frame) {
+        cur_frame->time_started = (uintptr_t)os_time_get_boot_microsecond();
+    }
+    else {
+        if (cur_frame->function) {
+            cur_frame->function->total_exec_time +=
+                os_time_get_boot_microsecond() - cur_frame->time_started;
+            cur_frame->function->total_exec_cnt++;
+        }
+    }
+#endif
+
+#if WASM_ENABLE_MEMORY_PROFILING != 0
+    if (alloc_frame) {
+        uint32 wasm_stack_used =
+            exec_env->wasm_stack.top - exec_env->wasm_stack.bottom;
+        if (wasm_stack_used > exec_env->max_wasm_stack_used)
+            exec_env->max_wasm_stack_used = wasm_stack_used;
+    }
+#endif
+}
 #endif /* end of WASM_ENABLE_DUMP_CALL_STACK != 0 \
           || WASM_ENABLE_PERF_PROFILING != 0      \
           || WASM_ENABLE_JIT_STACK_FRAME != 0 */

+ 3 - 0
core/iwasm/interpreter/wasm_runtime.h

@@ -731,6 +731,9 @@ llvm_jit_alloc_frame(WASMExecEnv *exec_env, uint32 func_index);
 
 void
 llvm_jit_free_frame(WASMExecEnv *exec_env);
+
+void
+llvm_jit_frame_update_profile_info(WASMExecEnv *exec_env, bool alloc_frame);
 #endif
 
 #if WASM_ENABLE_GC != 0

+ 2 - 0
core/shared/mem-alloc/ems/ems_hmu.c

@@ -48,7 +48,9 @@ hmu_init_prefix_and_suffix(hmu_t *hmu, gc_size_t tot_size,
 void
 hmu_verify(void *vheap, hmu_t *hmu)
 {
+#if BH_ENABLE_GC_CORRUPTION_CHECK != 0
     gc_heap_t *heap = (gc_heap_t *)vheap;
+#endif
     gc_object_prefix_t *prefix = NULL;
     gc_object_suffix_t *suffix = NULL;
     gc_uint32 i = 0;

+ 2 - 0
wamr-compiler/main.c

@@ -458,8 +458,10 @@ main(int argc, char *argv[])
         }
         else if (!strcmp(argv[0], "--enable-perf-profiling")) {
             option.enable_aux_stack_frame = true;
+            option.enable_perf_profiling = true;
         }
         else if (!strcmp(argv[0], "--enable-memory-profiling")) {
+            option.enable_memory_profiling = true;
             option.enable_stack_estimation = true;
         }
         else if (!strcmp(argv[0], "--xip")) {