Просмотр исходного кода

Merge branch main into dev/gc_refactor

Wenyong Huang 2 лет назад
Родитель
Сommit
e6d210a67f
36 измененных файлов с 1224 добавлено и 449 удалено
  1. 11 0
      build-scripts/config_common.cmake
  2. 5 0
      core/config.h
  3. 104 0
      core/iwasm/aot/aot_loader.c
  4. 23 12
      core/iwasm/aot/aot_runtime.c
  5. 52 87
      core/iwasm/common/wasm_c_api.c
  6. 2 0
      core/iwasm/common/wasm_c_api_internal.h
  7. 31 8
      core/iwasm/common/wasm_runtime_common.c
  8. 9 2
      core/iwasm/common/wasm_runtime_common.h
  9. 9 5
      core/iwasm/compilation/aot_llvm.c
  10. 2 2
      core/iwasm/compilation/aot_llvm.h
  11. 5 0
      core/iwasm/compilation/aot_llvm_extra.cpp
  12. 8 4
      core/iwasm/compilation/simd/simd_conversions.c
  13. 11 6
      core/iwasm/fast-jit/cg/x86-64/jit_codegen_x86_64.cpp
  14. 5 1
      core/iwasm/fast-jit/fe/jit_emit_numberic.c
  15. 0 1
      core/iwasm/fast-jit/jit_compiler.h
  16. 0 1
      core/iwasm/include/aot_comp_option.h
  17. 14 2
      core/iwasm/include/wasm_c_api.h
  18. 18 5
      core/iwasm/include/wasm_export.h
  19. 57 42
      core/iwasm/interpreter/wasm_interp_classic.c
  20. 0 4
      core/iwasm/interpreter/wasm_interp_fast.c
  21. 31 11
      core/iwasm/interpreter/wasm_loader.c
  22. 31 11
      core/iwasm/interpreter/wasm_mini_loader.c
  23. 23 12
      core/iwasm/interpreter/wasm_runtime.c
  24. 46 1
      core/shared/platform/common/freertos/freertos_thread.c
  25. 2 0
      core/shared/utils/bh_log.c
  26. 14 1
      doc/perf_tune.md
  27. 2 206
      doc/source_debugging.md
  28. 100 0
      doc/source_debugging_aot.md
  29. 115 0
      doc/source_debugging_interpreter.md
  30. 6 0
      product-mini/platforms/nuttx/wamr.mk
  31. 14 6
      product-mini/platforms/posix/main.c
  32. 1 0
      samples/sgx-ra/CMakeLists.txt
  33. 161 0
      test-tools/append-aot-to-wasm/append_aot_to_wasm.py
  34. 210 0
      test-tools/trans-jitted-func-name/trans_wasm_func_name.py
  35. 85 16
      wamr-compiler/CMakeLists.txt
  36. 17 3
      wamr-compiler/main.c

+ 11 - 0
build-scripts/config_common.cmake

@@ -154,6 +154,13 @@ elseif (NOT (WAMR_BUILD_SANITIZER STREQUAL "") )
   message(SEND_ERROR "Unsupported sanitizer: ${WAMR_BUILD_SANITIZER}")
   message(SEND_ERROR "Unsupported sanitizer: ${WAMR_BUILD_SANITIZER}")
 endif()
 endif()
 
 
+if (WAMR_BUILD_LINUX_PERF EQUAL 1)
+  if (NOT WAMR_BUILD_JIT AND NOT WAMR_BUILD_AOT)
+    message(WARNING "only support perf in aot and llvm-jit")
+    set(WAMR_BUILD_LINUX_PERF 0)
+  endif ()
+endif ()
+
 ########################################
 ########################################
 
 
 message ("-- Build Configurations:")
 message ("-- Build Configurations:")
@@ -480,3 +487,7 @@ if (WAMR_CONFIGUABLE_BOUNDS_CHECKS EQUAL 1)
   add_definitions (-DWASM_CONFIGURABLE_BOUNDS_CHECKS=1)
   add_definitions (-DWASM_CONFIGURABLE_BOUNDS_CHECKS=1)
   message ("     Configurable bounds checks enabled")
   message ("     Configurable bounds checks enabled")
 endif ()
 endif ()
+if (WAMR_BUILD_LINUX_PERF EQUAL 1)
+  add_definitions (-DWASM_ENABLE_LINUX_PERF=1)
+  message ("     Enable linux perf support")
+endif ()

+ 5 - 0
core/config.h

@@ -536,6 +536,11 @@
 #define WASM_MAX_INSTANCE_CONTEXTS 8
 #define WASM_MAX_INSTANCE_CONTEXTS 8
 #endif
 #endif
 
 
+/* linux perf support */
+#ifndef WASM_ENABLE_LINUX_PERF
+#define WASM_ENABLE_LINUX_PERF 0
+#endif
+
 #ifndef WASM_TABLE_MAX_SIZE
 #ifndef WASM_TABLE_MAX_SIZE
 #define WASM_TABLE_MAX_SIZE 1024
 #define WASM_TABLE_MAX_SIZE 1024
 #endif
 #endif

+ 104 - 0
core/iwasm/aot/aot_loader.c

@@ -3559,6 +3559,104 @@ fail:
     return ret;
     return ret;
 }
 }
 
 
+#if WASM_ENABLE_LINUX_PERF != 0
+struct func_info {
+    uint32 idx;
+    void *ptr;
+};
+
+static uint32
+get_func_size(const AOTModule *module, struct func_info *sorted_func_ptrs,
+              uint32 idx)
+{
+    uint32 func_sz;
+
+    if (idx == module->func_count - 1)
+        func_sz = (uintptr_t)module->code + module->code_size
+                  - (uintptr_t)(sorted_func_ptrs[idx].ptr);
+    else
+        func_sz = (uintptr_t)(sorted_func_ptrs[idx + 1].ptr)
+                  - (uintptr_t)(sorted_func_ptrs[idx].ptr);
+
+    return func_sz;
+}
+
+static int
+compare_func_ptrs(const void *f1, const void *f2)
+{
+    return (intptr_t)((struct func_info *)f1)->ptr
+           - (intptr_t)((struct func_info *)f2)->ptr;
+}
+
+static struct func_info *
+sort_func_ptrs(const AOTModule *module, char *error_buf, uint32 error_buf_size)
+{
+    uint64 content_len;
+    struct func_info *sorted_func_ptrs;
+    unsigned i;
+
+    content_len = (uint64)sizeof(struct func_info) * module->func_count;
+    sorted_func_ptrs = loader_malloc(content_len, error_buf, error_buf_size);
+    if (!sorted_func_ptrs)
+        return NULL;
+
+    for (i = 0; i < module->func_count; i++) {
+        sorted_func_ptrs[i].idx = i;
+        sorted_func_ptrs[i].ptr = module->func_ptrs[i];
+    }
+
+    qsort(sorted_func_ptrs, module->func_count, sizeof(struct func_info),
+          compare_func_ptrs);
+
+    return sorted_func_ptrs;
+}
+
+static bool
+create_perf_map(const AOTModule *module, char *error_buf, uint32 error_buf_size)
+{
+    struct func_info *sorted_func_ptrs = NULL;
+    char perf_map_info[128] = { 0 };
+    FILE *perf_map = NULL;
+    uint32 i;
+    pid_t pid = getpid();
+    bool ret = false;
+
+    sorted_func_ptrs = sort_func_ptrs(module, error_buf, error_buf_size);
+    if (!sorted_func_ptrs)
+        goto quit;
+
+    snprintf(perf_map_info, 128, "/tmp/perf-%d.map", pid);
+    perf_map = fopen(perf_map_info, "w");
+    if (!perf_map) {
+        LOG_WARNING("warning: can't create /tmp/perf-%d.map, because %s", pid,
+                    strerror(errno));
+        goto quit;
+    }
+
+    for (i = 0; i < module->func_count; i++) {
+        memset(perf_map_info, 0, 128);
+        snprintf(perf_map_info, 128, "%lx  %x  aot_func#%u\n",
+                 (uintptr_t)sorted_func_ptrs[i].ptr,
+                 get_func_size(module, sorted_func_ptrs, i),
+                 sorted_func_ptrs[i].idx);
+
+        fwrite(perf_map_info, 1, strlen(perf_map_info), perf_map);
+    }
+
+    LOG_VERBOSE("generate /tmp/perf-%d.map", pid);
+    ret = true;
+
+quit:
+    if (sorted_func_ptrs)
+        free(sorted_func_ptrs);
+
+    if (perf_map)
+        fclose(perf_map);
+
+    return ret;
+}
+#endif /* WASM_ENABLE_LINUX_PERF != 0*/
+
 static bool
 static bool
 load_from_sections(AOTModule *module, AOTSection *sections,
 load_from_sections(AOTModule *module, AOTSection *sections,
                    bool is_load_from_file_buf, char *error_buf,
                    bool is_load_from_file_buf, char *error_buf,
@@ -4040,6 +4138,12 @@ load(const uint8 *buf, uint32 size, AOTModule *module, char *error_buf,
     }
     }
 #endif
 #endif
 
 
+#if WASM_ENABLE_LINUX_PERF != 0
+    if (wasm_runtime_get_linux_perf())
+        if (!create_perf_map(module, error_buf, error_buf_size))
+            goto fail;
+#endif
+
     return ret;
     return ret;
 fail:
 fail:
     return false;
     return false;

+ 23 - 12
core/iwasm/aot/aot_runtime.c

@@ -1982,7 +1982,6 @@ aot_lookup_function(const AOTModuleInstance *module_inst, const char *name,
 }
 }
 
 
 #ifdef OS_ENABLE_HW_BOUND_CHECK
 #ifdef OS_ENABLE_HW_BOUND_CHECK
-
 static bool
 static bool
 invoke_native_with_hw_bound_check(WASMExecEnv *exec_env, void *func_ptr,
 invoke_native_with_hw_bound_check(WASMExecEnv *exec_env, void *func_ptr,
                                   const WASMFuncType *func_type,
                                   const WASMFuncType *func_type,
@@ -2014,19 +2013,26 @@ invoke_native_with_hw_bound_check(WASMExecEnv *exec_env, void *func_ptr,
         return false;
         return false;
     }
     }
 
 
-    if (exec_env_tls && (exec_env_tls != exec_env)) {
-        aot_set_exception(module_inst, "invalid exec env");
-        return false;
-    }
+    if (!exec_env_tls) {
+        if (!os_thread_signal_inited()) {
+            aot_set_exception(module_inst, "thread signal env not inited");
+            return false;
+        }
 
 
-    if (!os_thread_signal_inited()) {
-        aot_set_exception(module_inst, "thread signal env not inited");
-        return false;
+        /* Set thread handle and stack boundary if they haven't been set */
+        wasm_exec_env_set_thread_info(exec_env);
+
+        wasm_runtime_set_exec_env_tls(exec_env);
+    }
+    else {
+        if (exec_env_tls != exec_env) {
+            aot_set_exception(module_inst, "invalid exec env");
+            return false;
+        }
     }
     }
 
 
     wasm_exec_env_push_jmpbuf(exec_env, &jmpbuf_node);
     wasm_exec_env_push_jmpbuf(exec_env, &jmpbuf_node);
 
 
-    wasm_runtime_set_exec_env_tls(exec_env);
     if (os_setjmp(jmpbuf_node.jmpbuf) == 0) {
     if (os_setjmp(jmpbuf_node.jmpbuf) == 0) {
         /* Quick call with func_ptr if the function signature is simple */
         /* Quick call with func_ptr if the function signature is simple */
         if (!signature && param_count == 1 && types[0] == VALUE_TYPE_I32) {
         if (!signature && param_count == 1 && types[0] == VALUE_TYPE_I32) {
@@ -2081,7 +2087,6 @@ invoke_native_with_hw_bound_check(WASMExecEnv *exec_env, void *func_ptr,
     (void)jmpbuf_node_pop;
     (void)jmpbuf_node_pop;
     return ret;
     return ret;
 }
 }
-
 #define invoke_native_internal invoke_native_with_hw_bound_check
 #define invoke_native_internal invoke_native_with_hw_bound_check
 #else /* else of OS_ENABLE_HW_BOUND_CHECK */
 #else /* else of OS_ENABLE_HW_BOUND_CHECK */
 #define invoke_native_internal wasm_runtime_invoke_native
 #define invoke_native_internal wasm_runtime_invoke_native
@@ -2163,10 +2168,16 @@ aot_call_function(WASMExecEnv *exec_env, AOTFunctionInstance *function,
 
 
     /* func pointer was looked up previously */
     /* func pointer was looked up previously */
     bh_assert(func_ptr != NULL);
     bh_assert(func_ptr != NULL);
-    /* set thread handle and stack boundary */
+
+#ifndef OS_ENABLE_HW_BOUND_CHECK
+    /* Set thread handle and stack boundary */
     wasm_exec_env_set_thread_info(exec_env);
     wasm_exec_env_set_thread_info(exec_env);
+#else
+    /* Set thread info in invoke_native_with_hw_bound_check when
+       hw bound check is enabled */
+#endif
 
 
-    /* set exec env so it can be later retrieved from instance */
+    /* Set exec env so it can be later retrieved from instance */
     ((AOTModuleInstanceExtra *)module_inst->e)->common.cur_exec_env = exec_env;
     ((AOTModuleInstanceExtra *)module_inst->e)->common.cur_exec_env = exec_env;
 
 
     if (ext_ret_count > 0) {
     if (ext_ret_count > 0) {

+ 52 - 87
core/iwasm/common/wasm_c_api.c

@@ -299,6 +299,7 @@ wasm_config_new(void)
 
 
     memset(config, 0, sizeof(wasm_config_t));
     memset(config, 0, sizeof(wasm_config_t));
     config->mem_alloc_type = Alloc_With_System_Allocator;
     config->mem_alloc_type = Alloc_With_System_Allocator;
+
     return config;
     return config;
 }
 }
 
 
@@ -330,7 +331,17 @@ wasm_config_set_linux_perf_opt(wasm_config_t *config, bool enable)
     if (!config)
     if (!config)
         return NULL;
         return NULL;
 
 
-    config->linux_perf_support = enable;
+    config->enable_linux_perf = enable;
+    return config;
+}
+
+wasm_config_t *
+wasm_config_set_segue_flags(wasm_config_t *config, uint32 segue_flags)
+{
+    if (!config)
+        return NULL;
+
+    config->segue_flags = segue_flags;
     return config;
     return config;
 }
 }
 
 
@@ -380,7 +391,8 @@ wasm_engine_new_internal(wasm_config_t *config)
     init_args.mem_alloc_type = config->mem_alloc_type;
     init_args.mem_alloc_type = config->mem_alloc_type;
     memcpy(&init_args.mem_alloc_option, &config->mem_alloc_option,
     memcpy(&init_args.mem_alloc_option, &config->mem_alloc_option,
            sizeof(MemAllocOption));
            sizeof(MemAllocOption));
-    init_args.linux_perf_support = config->linux_perf_support;
+    init_args.enable_linux_perf = config->enable_linux_perf;
+    init_args.segue_flags = config->segue_flags;
 
 
     if (!wasm_runtime_full_init(&init_args)) {
     if (!wasm_runtime_full_init(&init_args)) {
         LOG_DEBUG("wasm_runtime_full_init failed");
         LOG_DEBUG("wasm_runtime_full_init failed");
@@ -2936,6 +2948,8 @@ wasm_func_new_basic(wasm_store_t *store, const wasm_functype_t *type,
     if (!(func->type = wasm_functype_copy(type))) {
     if (!(func->type = wasm_functype_copy(type))) {
         goto failed;
         goto failed;
     }
     }
+    func->param_count = func->type->params->num_elems;
+    func->result_count = func->type->results->num_elems;
 
 
     RETURN_OBJ(func, wasm_func_delete)
     RETURN_OBJ(func, wasm_func_delete)
 }
 }
@@ -2966,6 +2980,8 @@ wasm_func_new_with_env_basic(wasm_store_t *store, const wasm_functype_t *type,
     if (!(func->type = wasm_functype_copy(type))) {
     if (!(func->type = wasm_functype_copy(type))) {
         goto failed;
         goto failed;
     }
     }
+    func->param_count = func->type->params->num_elems;
+    func->result_count = func->type->results->num_elems;
 
 
     RETURN_OBJ(func, wasm_func_delete)
     RETURN_OBJ(func, wasm_func_delete)
 }
 }
@@ -3055,6 +3071,8 @@ wasm_func_new_internal(wasm_store_t *store, uint16 func_idx_rt,
     if (!func->type) {
     if (!func->type) {
         goto failed;
         goto failed;
     }
     }
+    func->param_count = func->type->params->num_elems;
+    func->result_count = func->type->results->num_elems;
 
 
     /* will add name information when processing "exports" */
     /* will add name information when processing "exports" */
     func->store = store;
     func->store = store;
@@ -3146,48 +3164,30 @@ params_to_argv(const wasm_val_vec_t *params,
                const wasm_valtype_vec_t *param_defs, uint32 *argv,
                const wasm_valtype_vec_t *param_defs, uint32 *argv,
                uint32 *ptr_argc)
                uint32 *ptr_argc)
 {
 {
-    size_t i = 0;
+    uint32 *argv_org = argv;
+    const wasm_val_t *param, *param_end;
 
 
-    if (!param_defs->num_elems) {
-        return true;
-    }
+    bh_assert(params && params->num_elems && params->size && params->data);
 
 
-    if (!params || !params->num_elems || !params->size || !params->data) {
-        LOG_ERROR("the parameter params is invalid");
-        return false;
-    }
-
-    *ptr_argc = 0;
-    for (i = 0; i < param_defs->num_elems; ++i) {
-        const wasm_val_t *param = params->data + i;
-        bh_assert((*(param_defs->data + i))->kind == param->kind);
+    param = params->data;
+    param_end = param + param_defs->num_elems;
 
 
+    for (; param < param_end; param++) {
         switch (param->kind) {
         switch (param->kind) {
             case WASM_I32:
             case WASM_I32:
+            case WASM_F32:
                 *(int32 *)argv = param->of.i32;
                 *(int32 *)argv = param->of.i32;
                 argv += 1;
                 argv += 1;
-                *ptr_argc += 1;
                 break;
                 break;
             case WASM_I64:
             case WASM_I64:
-                *(int64 *)argv = param->of.i64;
-                argv += 2;
-                *ptr_argc += 2;
-                break;
-            case WASM_F32:
-                *(float32 *)argv = param->of.f32;
-                argv += 1;
-                *ptr_argc += 1;
-                break;
             case WASM_F64:
             case WASM_F64:
-                *(float64 *)argv = param->of.f64;
+                *(int64 *)argv = param->of.i64;
                 argv += 2;
                 argv += 2;
-                *ptr_argc += 2;
                 break;
                 break;
 #if WASM_ENABLE_GC == 0 && WASM_ENABLE_REF_TYPES != 0
 #if WASM_ENABLE_GC == 0 && WASM_ENABLE_REF_TYPES != 0
             case WASM_ANYREF:
             case WASM_ANYREF:
                 *(uintptr_t *)argv = (uintptr_t)param->of.ref;
                 *(uintptr_t *)argv = (uintptr_t)param->of.ref;
                 argv += sizeof(uintptr_t) / sizeof(uint32);
                 argv += sizeof(uintptr_t) / sizeof(uint32);
-                *ptr_argc += 1;
                 break;
                 break;
 #endif
 #endif
             default:
             default:
@@ -3196,6 +3196,7 @@ params_to_argv(const wasm_val_vec_t *params,
         }
         }
     }
     }
 
 
+    *ptr_argc = (uint32)(argv - argv_org);
     return true;
     return true;
 }
 }
 
 
@@ -3203,62 +3204,37 @@ static bool
 argv_to_results(const uint32 *argv, const wasm_valtype_vec_t *result_defs,
 argv_to_results(const uint32 *argv, const wasm_valtype_vec_t *result_defs,
                 wasm_val_vec_t *results)
                 wasm_val_vec_t *results)
 {
 {
-    size_t i = 0, argv_i = 0;
+    wasm_valtype_t **result_def, **result_def_end;
     wasm_val_t *result;
     wasm_val_t *result;
 
 
-    if (!result_defs->num_elems) {
-        return true;
-    }
+    bh_assert(results && results->size && results->data);
 
 
-    if (!results || !results->size || !results->data) {
-        LOG_ERROR("the parameter results is invalid");
-        return false;
-    }
+    result_def = result_defs->data;
+    result_def_end = result_def + result_defs->num_elems;
+    result = results->data;
 
 
-    for (i = 0, result = results->data, argv_i = 0; i < result_defs->num_elems;
-         i++, result++) {
-        switch (result_defs->data[i]->kind) {
+    for (; result_def < result_def_end; result_def++, result++) {
+        result->kind = result_def[0]->kind;
+        switch (result->kind) {
             case WASM_I32:
             case WASM_I32:
-            {
-                result->kind = WASM_I32;
-                result->of.i32 = *(int32 *)(argv + argv_i);
-                argv_i += 1;
-                break;
-            }
-            case WASM_I64:
-            {
-                result->kind = WASM_I64;
-                result->of.i64 = *(int64 *)(argv + argv_i);
-                argv_i += 2;
-                break;
-            }
             case WASM_F32:
             case WASM_F32:
-            {
-                result->kind = WASM_F32;
-                result->of.f32 = *(float32 *)(argv + argv_i);
-                argv_i += 1;
+                result->of.i32 = *(int32 *)argv;
+                argv += 1;
                 break;
                 break;
-            }
+            case WASM_I64:
             case WASM_F64:
             case WASM_F64:
-            {
-                result->kind = WASM_F64;
-                result->of.f64 = *(float64 *)(argv + argv_i);
-                argv_i += 2;
+                result->of.i64 = *(int64 *)argv;
+                argv += 2;
                 break;
                 break;
-            }
 #if WASM_ENABLE_GC == 0 && WASM_ENABLE_REF_TYPES != 0
 #if WASM_ENABLE_GC == 0 && WASM_ENABLE_REF_TYPES != 0
             case WASM_ANYREF:
             case WASM_ANYREF:
-            {
-                result->kind = WASM_ANYREF;
-                result->of.ref =
-                    (struct wasm_ref_t *)(*(uintptr_t *)(argv + argv_i));
-                argv_i += sizeof(uintptr_t) / sizeof(uint32);
+                result->of.ref = (struct wasm_ref_t *)(*(uintptr_t *)argv);
+                argv += sizeof(uintptr_t) / sizeof(uint32);
                 break;
                 break;
-            }
 #endif
 #endif
             default:
             default:
                 LOG_WARNING("%s meets unsupported type: %d", __FUNCTION__,
                 LOG_WARNING("%s meets unsupported type: %d", __FUNCTION__,
-                            result_defs->data[i]->kind);
+                            result->kind);
                 return false;
                 return false;
         }
         }
     }
     }
@@ -3279,9 +3255,7 @@ wasm_func_call(const wasm_func_t *func, const wasm_val_vec_t *params,
     WASMExecEnv *exec_env = NULL;
     WASMExecEnv *exec_env = NULL;
     size_t param_count, result_count, alloc_count;
     size_t param_count, result_count, alloc_count;
 
 
-    if (!func) {
-        return NULL;
-    }
+    bh_assert(func && func->type);
 
 
     if (!func->inst_comm_rt) {
     if (!func->inst_comm_rt) {
         wasm_name_t message = { 0 };
         wasm_name_t message = { 0 };
@@ -3295,17 +3269,14 @@ wasm_func_call(const wasm_func_t *func, const wasm_val_vec_t *params,
         return trap;
         return trap;
     }
     }
 
 
-    bh_assert(func->type);
-
-#if WASM_ENABLE_INTERP != 0
     if (func->inst_comm_rt->module_type == Wasm_Module_Bytecode) {
     if (func->inst_comm_rt->module_type == Wasm_Module_Bytecode) {
+#if WASM_ENABLE_INTERP != 0
         func_comm_rt = ((WASMModuleInstance *)func->inst_comm_rt)->e->functions
         func_comm_rt = ((WASMModuleInstance *)func->inst_comm_rt)->e->functions
                        + func->func_idx_rt;
                        + func->func_idx_rt;
-    }
 #endif
 #endif
-
+    }
+    else if (func->inst_comm_rt->module_type == Wasm_Module_AoT) {
 #if WASM_ENABLE_AOT != 0
 #if WASM_ENABLE_AOT != 0
-    if (func->inst_comm_rt->module_type == Wasm_Module_AoT) {
         if (!(func_comm_rt = func->func_comm_rt)) {
         if (!(func_comm_rt = func->func_comm_rt)) {
             AOTModuleInstance *inst_aot =
             AOTModuleInstance *inst_aot =
                 (AOTModuleInstance *)func->inst_comm_rt;
                 (AOTModuleInstance *)func->inst_comm_rt;
@@ -3326,8 +3297,8 @@ wasm_func_call(const wasm_func_t *func, const wasm_val_vec_t *params,
                 }
                 }
             }
             }
         }
         }
-    }
 #endif
 #endif
+    }
 
 
     /*
     /*
      * a wrong combination of module filetype and compilation flags
      * a wrong combination of module filetype and compilation flags
@@ -3403,19 +3374,13 @@ failed:
 size_t
 size_t
 wasm_func_param_arity(const wasm_func_t *func)
 wasm_func_param_arity(const wasm_func_t *func)
 {
 {
-    if (!func || !func->type || !func->type->params) {
-        return 0;
-    }
-    return func->type->params->num_elems;
+    return func->param_count;
 }
 }
 
 
 size_t
 size_t
 wasm_func_result_arity(const wasm_func_t *func)
 wasm_func_result_arity(const wasm_func_t *func)
 {
 {
-    if (!func || !func->type || !func->type->results) {
-        return 0;
-    }
-    return func->type->results->num_elems;
+    return func->result_count;
 }
 }
 
 
 wasm_global_t *
 wasm_global_t *

+ 2 - 0
core/iwasm/common/wasm_c_api_internal.h

@@ -130,6 +130,8 @@ struct wasm_func_t {
 
 
     struct wasm_host_info host_info;
     struct wasm_host_info host_info;
     wasm_functype_t *type;
     wasm_functype_t *type;
+    uint16 param_count;
+    uint16 result_count;
 
 
     bool with_env;
     bool with_env;
     union {
     union {

+ 31 - 8
core/iwasm/common/wasm_runtime_common.c

@@ -161,7 +161,7 @@ static JitCompOptions jit_options = { 0 };
 #endif
 #endif
 
 
 #if WASM_ENABLE_JIT != 0
 #if WASM_ENABLE_JIT != 0
-static LLVMJITOptions llvm_jit_options = { 3, 3, 0, false };
+static LLVMJITOptions llvm_jit_options = { 3, 3, 0 };
 #endif
 #endif
 
 
 #if WASM_ENABLE_GC != 0
 #if WASM_ENABLE_GC != 0
@@ -681,14 +681,17 @@ wasm_runtime_full_init(RuntimeInitArgs *init_args)
 #endif
 #endif
 
 
 #if WASM_ENABLE_JIT != 0
 #if WASM_ENABLE_JIT != 0
-    LOG_DEBUG("Start LLVM_JIT, opt_sz=%u, opt_lvl=%u, segue=%s, linux_perf=%s",
-              init_args->llvm_jit_size_level, init_args->llvm_jit_opt_level,
-              init_args->segue_flags ? "Yes" : "No",
-              init_args->linux_perf_support ? "Yes" : "No");
     llvm_jit_options.size_level = init_args->llvm_jit_size_level;
     llvm_jit_options.size_level = init_args->llvm_jit_size_level;
     llvm_jit_options.opt_level = init_args->llvm_jit_opt_level;
     llvm_jit_options.opt_level = init_args->llvm_jit_opt_level;
     llvm_jit_options.segue_flags = init_args->segue_flags;
     llvm_jit_options.segue_flags = init_args->segue_flags;
-    llvm_jit_options.linux_perf_support = init_args->linux_perf_support;
+#endif
+
+#if WASM_ENABLE_LINUX_PERF != 0
+    wasm_runtime_set_linux_perf(init_args->enable_linux_perf);
+#else
+    if (init_args->enable_linux_perf)
+        LOG_WARNING("warning: to enable linux perf support, please recompile "
+                    "with -DWAMR_BUILD_LINUX_PERF=1");
 #endif
 #endif
 
 
     if (!wasm_runtime_env_init()) {
     if (!wasm_runtime_env_init()) {
@@ -720,6 +723,12 @@ wasm_runtime_full_init(RuntimeInitArgs *init_args)
     return true;
     return true;
 }
 }
 
 
+void
+wasm_runtime_set_log_level(log_level_t level)
+{
+    bh_log_set_verbose_level(level);
+}
+
 bool
 bool
 wasm_runtime_is_running_mode_supported(RunningMode running_mode)
 wasm_runtime_is_running_mode_supported(RunningMode running_mode)
 {
 {
@@ -2598,7 +2607,6 @@ wasm_runtime_clear_exception(WASMModuleInstanceCommon *module_inst_comm)
     wasm_runtime_set_exception(module_inst_comm, NULL);
     wasm_runtime_set_exception(module_inst_comm, NULL);
 }
 }
 
 
-#if WASM_ENABLE_THREAD_MGR != 0
 void
 void
 wasm_runtime_terminate(WASMModuleInstanceCommon *module_inst_comm)
 wasm_runtime_terminate(WASMModuleInstanceCommon *module_inst_comm)
 {
 {
@@ -2608,7 +2616,6 @@ wasm_runtime_terminate(WASMModuleInstanceCommon *module_inst_comm)
               || module_inst_comm->module_type == Wasm_Module_AoT);
               || module_inst_comm->module_type == Wasm_Module_AoT);
     wasm_set_exception(module_inst, "terminated by user");
     wasm_set_exception(module_inst, "terminated by user");
 }
 }
-#endif
 
 
 void
 void
 wasm_runtime_set_custom_data_internal(
 wasm_runtime_set_custom_data_internal(
@@ -6412,3 +6419,19 @@ wasm_runtime_get_context(WASMModuleInstanceCommon *inst, void *key)
     return wasm_native_get_context(inst, key);
     return wasm_native_get_context(inst, key);
 }
 }
 #endif /* WASM_ENABLE_MODULE_INST_CONTEXT != 0 */
 #endif /* WASM_ENABLE_MODULE_INST_CONTEXT != 0 */
+
+#if WASM_ENABLE_LINUX_PERF != 0
+static bool enable_linux_perf = false;
+
+bool
+wasm_runtime_get_linux_perf(void)
+{
+    return enable_linux_perf;
+}
+
+void
+wasm_runtime_set_linux_perf(bool flag)
+{
+    enable_linux_perf = flag;
+}
+#endif

+ 9 - 2
core/iwasm/common/wasm_runtime_common.h

@@ -484,12 +484,11 @@ typedef struct wasm_frame_t {
     uint32 *lp;
     uint32 *lp;
 } WASMCApiFrame;
 } WASMCApiFrame;
 
 
-#ifdef WASM_ENABLE_JIT
+#if WASM_ENABLE_JIT != 0
 typedef struct LLVMJITOptions {
 typedef struct LLVMJITOptions {
     uint32 opt_level;
     uint32 opt_level;
     uint32 size_level;
     uint32 size_level;
     uint32 segue_flags;
     uint32 segue_flags;
-    bool linux_perf_support;
 } LLVMJITOptions;
 } LLVMJITOptions;
 #endif
 #endif
 
 
@@ -1177,6 +1176,14 @@ wasm_runtime_end_blocking_op(WASMExecEnv *exec_env);
 void
 void
 wasm_runtime_interrupt_blocking_op(WASMExecEnv *exec_env);
 wasm_runtime_interrupt_blocking_op(WASMExecEnv *exec_env);
 
 
+#if WASM_ENABLE_LINUX_PERF != 0
+bool
+wasm_runtime_get_linux_perf(void);
+
+void
+wasm_runtime_set_linux_perf(bool flag);
+#endif
+
 #ifdef __cplusplus
 #ifdef __cplusplus
 }
 }
 #endif
 #endif

+ 9 - 5
core/iwasm/compilation/aot_llvm.c

@@ -2346,7 +2346,7 @@ jit_stack_size_callback(void *user_data, const char *name, size_t namelen,
 }
 }
 
 
 static bool
 static bool
-orc_jit_create(AOTCompContext *comp_ctx, bool linux_perf_support)
+orc_jit_create(AOTCompContext *comp_ctx)
 {
 {
     LLVMErrorRef err;
     LLVMErrorRef err;
     LLVMOrcLLLazyJITRef orc_jit = NULL;
     LLVMOrcLLLazyJITRef orc_jit = NULL;
@@ -2386,13 +2386,15 @@ orc_jit_create(AOTCompContext *comp_ctx, bool linux_perf_support)
     /* Ownership transfer: LLVMOrcLLJITBuilderRef -> LLVMOrcLLJITRef */
     /* Ownership transfer: LLVMOrcLLJITBuilderRef -> LLVMOrcLLJITRef */
     builder = NULL;
     builder = NULL;
 
 
-    if (linux_perf_support) {
-        LOG_DEBUG("Enable linux perf support");
+#if WASM_ENABLE_LINUX_PERF != 0
+    if (wasm_runtime_get_linux_perf()) {
+        LOG_DEBUG("Enable linux perf support in JIT");
         LLVMOrcObjectLayerRef obj_linking_layer =
         LLVMOrcObjectLayerRef obj_linking_layer =
             (LLVMOrcObjectLayerRef)LLVMOrcLLLazyJITGetObjLinkingLayer(orc_jit);
             (LLVMOrcObjectLayerRef)LLVMOrcLLLazyJITGetObjLinkingLayer(orc_jit);
         LLVMOrcRTDyldObjectLinkingLayerRegisterJITEventListener(
         LLVMOrcRTDyldObjectLinkingLayerRegisterJITEventListener(
             obj_linking_layer, LLVMCreatePerfJITEventListener());
             obj_linking_layer, LLVMCreatePerfJITEventListener());
     }
     }
+#endif
 
 
     /* Ownership transfer: local -> AOTCompContext */
     /* Ownership transfer: local -> AOTCompContext */
     comp_ctx->orc_jit = orc_jit;
     comp_ctx->orc_jit = orc_jit;
@@ -2492,7 +2494,8 @@ aot_create_comp_context(const AOTCompData *comp_data, aot_comp_option_t option)
         goto fail;
         goto fail;
     }
     }
 
 
-    if (option->linux_perf_support) {
+#if WASM_ENABLE_LINUX_PERF != 0
+    if (wasm_runtime_get_linux_perf()) {
         /* FramePointerKind.All */
         /* FramePointerKind.All */
         LLVMMetadataRef val =
         LLVMMetadataRef val =
             LLVMValueAsMetadata(LLVMConstInt(LLVMInt32Type(), 2, false));
             LLVMValueAsMetadata(LLVMConstInt(LLVMInt32Type(), 2, false));
@@ -2502,6 +2505,7 @@ aot_create_comp_context(const AOTCompData *comp_data, aot_comp_option_t option)
 
 
         comp_ctx->emit_frame_pointer = true;
         comp_ctx->emit_frame_pointer = true;
     }
     }
+#endif
 
 
     if (BH_LIST_ERROR == bh_list_init(&comp_ctx->native_symbols)) {
     if (BH_LIST_ERROR == bh_list_init(&comp_ctx->native_symbols)) {
         goto fail;
         goto fail;
@@ -2617,7 +2621,7 @@ aot_create_comp_context(const AOTCompData *comp_data, aot_comp_option_t option)
             goto fail;
             goto fail;
 
 
         /* Create LLJIT Instance */
         /* Create LLJIT Instance */
-        if (!orc_jit_create(comp_ctx, option->linux_perf_support))
+        if (!orc_jit_create(comp_ctx))
             goto fail;
             goto fail;
     }
     }
     else {
     else {

+ 2 - 2
core/iwasm/compilation/aot_llvm.h

@@ -389,10 +389,10 @@ typedef struct AOTCompContext {
     /* Bulk memory feature */
     /* Bulk memory feature */
     bool enable_bulk_memory;
     bool enable_bulk_memory;
 
 
-    /* Bounday Check */
+    /* Boundary Check */
     bool enable_bound_check;
     bool enable_bound_check;
 
 
-    /* Native stack bounday Check */
+    /* Native stack boundary Check */
     bool enable_stack_bound_check;
     bool enable_stack_bound_check;
 
 
     /* Native stack usage estimation */
     /* Native stack usage estimation */

+ 5 - 0
core/iwasm/compilation/aot_llvm_extra.cpp

@@ -45,6 +45,7 @@
 #include <llvm/Transforms/Vectorize/LoopVectorize.h>
 #include <llvm/Transforms/Vectorize/LoopVectorize.h>
 #include <llvm/Transforms/Vectorize/LoadStoreVectorizer.h>
 #include <llvm/Transforms/Vectorize/LoadStoreVectorizer.h>
 #include <llvm/Transforms/Vectorize/SLPVectorizer.h>
 #include <llvm/Transforms/Vectorize/SLPVectorizer.h>
+#include <llvm/Transforms/Vectorize/VectorCombine.h>
 #include <llvm/Transforms/Scalar/LoopRotation.h>
 #include <llvm/Transforms/Scalar/LoopRotation.h>
 #include <llvm/Transforms/Scalar/SimpleLoopUnswitch.h>
 #include <llvm/Transforms/Scalar/SimpleLoopUnswitch.h>
 #include <llvm/Transforms/Scalar/LICM.h>
 #include <llvm/Transforms/Scalar/LICM.h>
@@ -315,8 +316,11 @@ aot_apply_llvm_new_pass_manager(AOTCompContext *comp_ctx, LLVMModuleRef module)
     }
     }
 
 
     ModulePassManager MPM;
     ModulePassManager MPM;
+
     if (comp_ctx->is_jit_mode) {
     if (comp_ctx->is_jit_mode) {
         const char *Passes =
         const char *Passes =
+            "loop-vectorize,slp-vectorizer,"
+            "load-store-vectorizer,vector-combine,"
             "mem2reg,instcombine,simplifycfg,jump-threading,indvars";
             "mem2reg,instcombine,simplifycfg,jump-threading,indvars";
         ExitOnErr(PB.parsePassPipeline(MPM, Passes));
         ExitOnErr(PB.parsePassPipeline(MPM, Passes));
     }
     }
@@ -327,6 +331,7 @@ aot_apply_llvm_new_pass_manager(AOTCompContext *comp_ctx, LLVMModuleRef module)
         FPM.addPass(LoopVectorizePass());
         FPM.addPass(LoopVectorizePass());
         FPM.addPass(SLPVectorizerPass());
         FPM.addPass(SLPVectorizerPass());
         FPM.addPass(LoadStoreVectorizerPass());
         FPM.addPass(LoadStoreVectorizerPass());
+        FPM.addPass(VectorCombinePass());
 
 
         if (comp_ctx->enable_llvm_pgo || comp_ctx->use_prof_file) {
         if (comp_ctx->enable_llvm_pgo || comp_ctx->use_prof_file) {
             /* LICM pass: loop invariant code motion, attempting to remove
             /* LICM pass: loop invariant code motion, attempting to remove

+ 8 - 4
core/iwasm/compilation/simd/simd_conversions.c

@@ -158,11 +158,15 @@ simd_integer_narrow_common(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
         return false;
         return false;
     }
     }
 
 
-    /* sat */
+    /* Refer to:
+     * https://github.com/WebAssembly/spec/blob/main/proposals/simd/SIMD.md#integer-to-integer-narrowing
+     * Regardless of the whether the operation is signed or unsigned, the input
+     * lanes are interpreted as signed integers.
+     */
     if (!(vec1 = simd_saturate(comp_ctx, func_ctx, e_sat_i16x8, vec1, min, max,
     if (!(vec1 = simd_saturate(comp_ctx, func_ctx, e_sat_i16x8, vec1, min, max,
-                               is_signed))
+                               true))
         || !(vec2 = simd_saturate(comp_ctx, func_ctx, e_sat_i16x8, vec2, min,
         || !(vec2 = simd_saturate(comp_ctx, func_ctx, e_sat_i16x8, vec2, min,
-                                  max, is_signed))) {
+                                  max, true))) {
         return false;
         return false;
     }
     }
 
 
@@ -740,4 +744,4 @@ aot_compile_simd_i64x2_extmul_i32x4(AOTCompContext *comp_ctx,
 {
 {
     return simd_integer_extmul(comp_ctx, func_ctx, lower_half, is_signed,
     return simd_integer_extmul(comp_ctx, func_ctx, lower_half, is_signed,
                                e_i64x2_extmul_i32x4);
                                e_i64x2_extmul_i32x4);
-}
+}

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

@@ -4379,13 +4379,18 @@ cmp_r_r_to_r_i32(x86::Assembler &a, int32 reg_no_dst, int32 reg_no1_src,
  * @return true if success, false otherwise
  * @return true if success, false otherwise
  */
  */
 static bool
 static bool
-cmp_imm_imm_to_r_i64(x86::Assembler &a, int32 reg_no_dst, int32 data1_src,
-                     int32 data2_src)
+cmp_imm_imm_to_r_i64(x86::Assembler &a, int32 reg_no_dst, int64 data1_src,
+                     int64 data2_src)
 {
 {
-    Imm imm(data1_src);
-    a.mov(regs_i64[REG_I64_FREE_IDX], imm);
-    imm.setValue(data2_src);
-    a.cmp(regs_i64[REG_I64_FREE_IDX], imm);
+    /* imm -> m64 */
+    const JitHardRegInfo *hreg_info = jit_codegen_get_hreg_info();
+    x86::Mem mem = x86::qword_ptr(regs_i64[hreg_info->exec_env_hreg_index],
+                                  offsetof(WASMExecEnv, jit_cache));
+    Imm imm(data2_src);
+    mov_imm_to_m(a, mem, imm, 8);
+
+    a.mov(regs_i64[REG_I64_FREE_IDX], data1_src);
+    a.cmp(regs_i64[REG_I64_FREE_IDX], mem);
     (void)reg_no_dst;
     (void)reg_no_dst;
     return true;
     return true;
 }
 }

+ 5 - 1
core/iwasm/fast-jit/fe/jit_emit_numberic.c

@@ -1066,13 +1066,15 @@ DEF_UNI_INT_CONST_OPS(shru)
 static int32
 static int32
 do_i32_const_shl(int32 lhs, int32 rhs)
 do_i32_const_shl(int32 lhs, int32 rhs)
 {
 {
+    rhs &= 31;
     return (int32)((uint32)lhs << (uint32)rhs);
     return (int32)((uint32)lhs << (uint32)rhs);
 }
 }
 
 
 static int64
 static int64
 do_i64_const_shl(int64 lhs, int64 rhs)
 do_i64_const_shl(int64 lhs, int64 rhs)
 {
 {
-    return (int32)((uint64)lhs << (uint64)rhs);
+    rhs &= 63LL;
+    return (uint64)lhs << (uint64)rhs;
 }
 }
 
 
 DEF_BI_INT_CONST_OPS(shrs, >>)
 DEF_BI_INT_CONST_OPS(shrs, >>)
@@ -1080,12 +1082,14 @@ DEF_BI_INT_CONST_OPS(shrs, >>)
 static int32
 static int32
 do_i32_const_shru(int32 lhs, int32 rhs)
 do_i32_const_shru(int32 lhs, int32 rhs)
 {
 {
+    rhs &= 31;
     return (uint32)lhs >> rhs;
     return (uint32)lhs >> rhs;
 }
 }
 
 
 static int64
 static int64
 do_i64_const_shru(int64 lhs, int64 rhs)
 do_i64_const_shru(int64 lhs, int64 rhs)
 {
 {
+    rhs &= 63LL;
     return (uint64)lhs >> rhs;
     return (uint64)lhs >> rhs;
 }
 }
 
 

+ 0 - 1
core/iwasm/fast-jit/jit_compiler.h

@@ -70,7 +70,6 @@ typedef struct JitInterpSwitchInfo {
 typedef struct JitCompOptions {
 typedef struct JitCompOptions {
     uint32 code_cache_size;
     uint32 code_cache_size;
     uint32 opt_level;
     uint32 opt_level;
-    bool linux_perf_support;
 } JitCompOptions;
 } JitCompOptions;
 
 
 bool
 bool

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

@@ -28,7 +28,6 @@ typedef struct AOTCompOption {
     bool enable_llvm_pgo;
     bool enable_llvm_pgo;
     bool enable_stack_estimation;
     bool enable_stack_estimation;
     bool enable_gc;
     bool enable_gc;
-    bool linux_perf_support;
     char *use_prof_file;
     char *use_prof_file;
     uint32_t opt_level;
     uint32_t opt_level;
     uint32_t size_level;
     uint32_t size_level;

+ 14 - 2
core/iwasm/include/wasm_c_api.h

@@ -181,7 +181,8 @@ typedef union MemAllocOption {
 struct wasm_config_t {
 struct wasm_config_t {
     mem_alloc_type_t mem_alloc_type;
     mem_alloc_type_t mem_alloc_type;
     MemAllocOption mem_alloc_option;
     MemAllocOption mem_alloc_option;
-    bool linux_perf_support;
+    uint32_t segue_flags;
+    bool enable_linux_perf;
     /*TODO: wasi args*/
     /*TODO: wasi args*/
 };
 };
 
 
@@ -189,7 +190,7 @@ struct wasm_config_t {
  * by default:
  * by default:
  * - mem_alloc_type is Alloc_With_System_Allocator
  * - mem_alloc_type is Alloc_With_System_Allocator
  * - mem_alloc_option is all 0
  * - mem_alloc_option is all 0
- * - linux_perf_support is false
+ * - enable_linux_perf is false
  */
  */
 WASM_API_EXTERN own wasm_config_t* wasm_config_new(void);
 WASM_API_EXTERN own wasm_config_t* wasm_config_new(void);
 
 
@@ -200,6 +201,17 @@ wasm_config_set_mem_alloc_opt(wasm_config_t *, mem_alloc_type_t, MemAllocOption
 WASM_API_EXTERN own wasm_config_t*
 WASM_API_EXTERN own wasm_config_t*
 wasm_config_set_linux_perf_opt(wasm_config_t *, bool);
 wasm_config_set_linux_perf_opt(wasm_config_t *, bool);
 
 
+/**
+ * Enable using GS register as the base address of linear memory in linux x86_64,
+ * which may speedup the linear memory access for LLVM AOT/JIT:
+ *   bit0 to bit4 denotes i32.load, i64.load, f32.load, f64.load, v128.load
+ *   bit8 to bit12 denotes i32.store, i64.store, f32.store, f64.store, v128.store
+ * For example, 0x01 enables i32.load, 0x0100 enables i32.store.
+ * To enable all load/store operations, use 0x1F1F
+ */
+WASM_API_EXTERN wasm_config_t*
+wasm_config_set_segue_flags(wasm_config_t *config, uint32_t segue_flags);
+
 // Engine
 // Engine
 
 
 WASM_DECLARE_OWN(engine)
 WASM_DECLARE_OWN(engine)

+ 18 - 5
core/iwasm/include/wasm_export.h

@@ -175,12 +175,12 @@ typedef struct RuntimeInitArgs {
     /**
     /**
      * If enabled
      * If enabled
      * - llvm-jit will output a jitdump file for `perf inject`
      * - llvm-jit will output a jitdump file for `perf inject`
-     * - aot. TBD
+     * - aot will output a perf-${pid}.map for `perf record`
      * - fast-jit. TBD
      * - fast-jit. TBD
      * - multi-tier-jit. TBD
      * - multi-tier-jit. TBD
      * - interpreter. TBD
      * - interpreter. TBD
      */
      */
-    bool linux_perf_support;
+    bool enable_linux_perf;
 } RuntimeInitArgs;
 } RuntimeInitArgs;
 
 
 #ifndef WASM_VALKIND_T_DEFINED
 #ifndef WASM_VALKIND_T_DEFINED
@@ -215,6 +215,14 @@ typedef struct wasm_val_t {
 } wasm_val_t;
 } wasm_val_t;
 #endif
 #endif
 
 
+typedef enum {
+    WASM_LOG_LEVEL_FATAL = 0,
+    WASM_LOG_LEVEL_ERROR = 1,
+    WASM_LOG_LEVEL_WARNING = 2,
+    WASM_LOG_LEVEL_DEBUG = 3,
+    WASM_LOG_LEVEL_VERBOSE = 4
+} log_level_t;
+
 /**
 /**
  * Initialize the WASM runtime environment, and also initialize
  * Initialize the WASM runtime environment, and also initialize
  * the memory allocator with system allocator, which calls os_malloc
  * the memory allocator with system allocator, which calls os_malloc
@@ -237,6 +245,14 @@ wasm_runtime_init(void);
 WASM_RUNTIME_API_EXTERN bool
 WASM_RUNTIME_API_EXTERN bool
 wasm_runtime_full_init(RuntimeInitArgs *init_args);
 wasm_runtime_full_init(RuntimeInitArgs *init_args);
 
 
+/**
+ * Set the log level. To be called after the runtime is initialized.
+ *
+ * @param level the log level to set
+ */
+WASM_RUNTIME_API_EXTERN void
+wasm_runtime_set_log_level(log_level_t level);
+
 /**
 /**
  * Query whether a certain running mode is supported for the runtime
  * Query whether a certain running mode is supported for the runtime
  *
  *
@@ -927,9 +943,6 @@ wasm_runtime_clear_exception(wasm_module_inst_t module_inst);
  *  - Another thread has a copy of `wasm_module_inst_t` of
  *  - Another thread has a copy of `wasm_module_inst_t` of
  *    the module instance and wants to terminate it asynchronously.
  *    the module instance and wants to terminate it asynchronously.
  *
  *
- * This function is provided only when WAMR is built with threading enabled.
- * (`WASM_ENABLE_THREAD_MGR=1`)
- *
  * @param module_inst the WASM module instance
  * @param module_inst the WASM module instance
  */
  */
 WASM_RUNTIME_API_EXTERN void
 WASM_RUNTIME_API_EXTERN void

+ 57 - 42
core/iwasm/interpreter/wasm_interp_classic.c

@@ -3999,11 +3999,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
 #if !defined(OS_ENABLE_HW_BOUND_CHECK)              \
 #if !defined(OS_ENABLE_HW_BOUND_CHECK)              \
     || WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0 \
     || WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0 \
     || WASM_ENABLE_BULK_MEMORY != 0
     || WASM_ENABLE_BULK_MEMORY != 0
-#if WASM_ENABLE_THREAD_MGR == 0
-                    linear_mem_size = memory->memory_data_size;
-#else
                     linear_mem_size = GET_LINEAR_MEMORY_SIZE(memory);
                     linear_mem_size = GET_LINEAR_MEMORY_SIZE(memory);
-#endif
 #endif
 #endif
                 }
                 }
 
 
@@ -6048,7 +6044,7 @@ llvm_jit_call_func_bytecode(WASMModuleInstance *module_inst,
     uint32 result_count = func_type->result_count;
     uint32 result_count = func_type->result_count;
     uint32 ext_ret_count = result_count > 1 ? result_count - 1 : 0;
     uint32 ext_ret_count = result_count > 1 ? result_count - 1 : 0;
     uint32 func_idx = (uint32)(function - module_inst->e->functions);
     uint32 func_idx = (uint32)(function - module_inst->e->functions);
-    bool ret;
+    bool ret = false;
 
 
 #if (WASM_ENABLE_DUMP_CALL_STACK != 0) || (WASM_ENABLE_PERF_PROFILING != 0) \
 #if (WASM_ENABLE_DUMP_CALL_STACK != 0) || (WASM_ENABLE_PERF_PROFILING != 0) \
     || (WASM_ENABLE_JIT_STACK_FRAME != 0)
     || (WASM_ENABLE_JIT_STACK_FRAME != 0)
@@ -6136,7 +6132,6 @@ llvm_jit_call_func_bytecode(WASMModuleInstance *module_inst,
 
 
         if (argv1 != argv1_buf)
         if (argv1 != argv1_buf)
             wasm_runtime_free(argv1);
             wasm_runtime_free(argv1);
-
         ret = true;
         ret = true;
     }
     }
     else {
     else {
@@ -6164,16 +6159,11 @@ wasm_interp_call_wasm(WASMModuleInstance *module_inst, WASMExecEnv *exec_env,
                       WASMFunctionInstance *function, uint32 argc,
                       WASMFunctionInstance *function, uint32 argc,
                       uint32 argv[])
                       uint32 argv[])
 {
 {
-    WASMRuntimeFrame *prev_frame = wasm_exec_env_get_cur_frame(exec_env);
-    WASMInterpFrame *frame, *outs_area;
+    WASMRuntimeFrame *frame = NULL, *prev_frame, *outs_area;
+    RunningMode running_mode =
+        wasm_runtime_get_running_mode((WASMModuleInstanceCommon *)module_inst);
     /* Allocate sufficient cells for all kinds of return values.  */
     /* Allocate sufficient cells for all kinds of return values.  */
-    unsigned all_cell_num =
-        function->ret_cell_num > 2 ? function->ret_cell_num : 2;
-    /* This frame won't be used by JITed code, so only allocate interp
-       frame here.  */
-    unsigned frame_size = wasm_interp_interp_frame_size(all_cell_num);
-    unsigned i;
-    bool copy_argv_from_frame = true;
+    bool alloc_frame = true;
 
 
     if (argc < function->param_cell_num) {
     if (argc < function->param_cell_num) {
         char buf[128];
         char buf[128];
@@ -6196,25 +6186,56 @@ wasm_interp_call_wasm(WASMModuleInstance *module_inst, WASMExecEnv *exec_env,
     }
     }
 #endif
 #endif
 
 
-    if (!(frame = ALLOC_FRAME(exec_env, frame_size, prev_frame)))
-        return;
+    if (!function->is_import_func) {
+        /* No need to alloc frame when calling LLVM JIT function */
+#if WASM_ENABLE_JIT != 0
+        if (running_mode == Mode_LLVM_JIT) {
+            alloc_frame = false;
+        }
+#if WASM_ENABLE_LAZY_JIT != 0 && WASM_ENABLE_FAST_JIT != 0
+        else if (running_mode == Mode_Multi_Tier_JIT) {
+            /* Tier-up from Fast JIT to LLVM JIT, call llvm jit function
+               if it is compiled, else call fast jit function */
+            uint32 func_idx = (uint32)(function - module_inst->e->functions);
+            if (module_inst->module->func_ptrs_compiled
+                    [func_idx - module_inst->module->import_function_count]) {
+                alloc_frame = false;
+            }
+        }
+#endif
+#endif
+    }
 
 
-    outs_area = wasm_exec_env_wasm_stack_top(exec_env);
-    frame->function = NULL;
-    frame->ip = NULL;
-    /* There is no local variable. */
-    frame->sp = frame->lp + 0;
+    if (alloc_frame) {
+        unsigned all_cell_num =
+            function->ret_cell_num > 2 ? function->ret_cell_num : 2;
+        unsigned frame_size;
 
 
-    if ((uint8 *)(outs_area->lp + function->param_cell_num)
-        > exec_env->wasm_stack.top_boundary) {
-        wasm_set_exception(module_inst, "wasm operand stack overflow");
-        return;
-    }
+        prev_frame = wasm_exec_env_get_cur_frame(exec_env);
+        /* This frame won't be used by JITed code, so only allocate interp
+           frame here.  */
+        frame_size = wasm_interp_interp_frame_size(all_cell_num);
 
 
-    if (argc > 0)
-        word_copy(outs_area->lp, argv, argc);
+        if (!(frame = ALLOC_FRAME(exec_env, frame_size, prev_frame)))
+            return;
 
 
-    wasm_exec_env_set_cur_frame(exec_env, frame);
+        outs_area = wasm_exec_env_wasm_stack_top(exec_env);
+        frame->function = NULL;
+        frame->ip = NULL;
+        /* There is no local variable. */
+        frame->sp = frame->lp + 0;
+
+        if ((uint8 *)(outs_area->lp + function->param_cell_num)
+            > exec_env->wasm_stack.top_boundary) {
+            wasm_set_exception(module_inst, "wasm operand stack overflow");
+            return;
+        }
+
+        if (argc > 0)
+            word_copy(outs_area->lp, argv, argc);
+
+        wasm_exec_env_set_cur_frame(exec_env, frame);
+    }
 
 
 #if defined(os_writegsbase)
 #if defined(os_writegsbase)
     {
     {
@@ -6240,9 +6261,6 @@ wasm_interp_call_wasm(WASMModuleInstance *module_inst, WASMExecEnv *exec_env,
         }
         }
     }
     }
     else {
     else {
-        RunningMode running_mode =
-            wasm_runtime_get_running_mode((wasm_module_inst_t)module_inst);
-
         if (running_mode == Mode_Interp) {
         if (running_mode == Mode_Interp) {
             wasm_interp_call_func_bytecode(module_inst, exec_env, function,
             wasm_interp_call_func_bytecode(module_inst, exec_env, function,
                                            frame);
                                            frame);
@@ -6256,9 +6274,6 @@ wasm_interp_call_wasm(WASMModuleInstance *module_inst, WASMExecEnv *exec_env,
         else if (running_mode == Mode_LLVM_JIT) {
         else if (running_mode == Mode_LLVM_JIT) {
             llvm_jit_call_func_bytecode(module_inst, exec_env, function, argc,
             llvm_jit_call_func_bytecode(module_inst, exec_env, function, argc,
                                         argv);
                                         argv);
-            /* For llvm jit, the results have been stored in argv,
-               no need to copy them from stack frame again */
-            copy_argv_from_frame = false;
         }
         }
 #endif
 #endif
 #if WASM_ENABLE_LAZY_JIT != 0 && WASM_ENABLE_FAST_JIT != 0 \
 #if WASM_ENABLE_LAZY_JIT != 0 && WASM_ENABLE_FAST_JIT != 0 \
@@ -6271,9 +6286,6 @@ wasm_interp_call_wasm(WASMModuleInstance *module_inst, WASMExecEnv *exec_env,
                     [func_idx - module_inst->module->import_function_count]) {
                     [func_idx - module_inst->module->import_function_count]) {
                 llvm_jit_call_func_bytecode(module_inst, exec_env, function,
                 llvm_jit_call_func_bytecode(module_inst, exec_env, function,
                                             argc, argv);
                                             argc, argv);
-                /* For llvm jit, the results have been stored in argv,
-                   no need to copy them from stack frame again */
-                copy_argv_from_frame = false;
             }
             }
             else {
             else {
                 fast_jit_call_func_bytecode(module_inst, exec_env, function,
                 fast_jit_call_func_bytecode(module_inst, exec_env, function,
@@ -6294,7 +6306,8 @@ wasm_interp_call_wasm(WASMModuleInstance *module_inst, WASMExecEnv *exec_env,
 
 
     /* Output the return value to the caller */
     /* Output the return value to the caller */
     if (!wasm_copy_exception(module_inst, NULL)) {
     if (!wasm_copy_exception(module_inst, NULL)) {
-        if (copy_argv_from_frame) {
+        if (alloc_frame) {
+            uint32 i;
             for (i = 0; i < function->ret_cell_num; i++) {
             for (i = 0; i < function->ret_cell_num; i++) {
                 argv[i] = *(frame->sp + i - function->ret_cell_num);
                 argv[i] = *(frame->sp + i - function->ret_cell_num);
             }
             }
@@ -6308,6 +6321,8 @@ wasm_interp_call_wasm(WASMModuleInstance *module_inst, WASMExecEnv *exec_env,
 #endif
 #endif
     }
     }
 
 
-    wasm_exec_env_set_cur_frame(exec_env, prev_frame);
-    FREE_FRAME(exec_env, frame);
+    if (alloc_frame) {
+        wasm_exec_env_set_cur_frame(exec_env, prev_frame);
+        FREE_FRAME(exec_env, frame);
+    }
 }
 }

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

@@ -3817,11 +3817,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
 #if !defined(OS_ENABLE_HW_BOUND_CHECK)              \
 #if !defined(OS_ENABLE_HW_BOUND_CHECK)              \
     || WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0 \
     || WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0 \
     || WASM_ENABLE_BULK_MEMORY != 0
     || WASM_ENABLE_BULK_MEMORY != 0
-#if WASM_ENABLE_THREAD_MGR == 0
-                    linear_mem_size = memory->memory_data_size;
-#else
                     linear_mem_size = GET_LINEAR_MEMORY_SIZE(memory);
                     linear_mem_size = GET_LINEAR_MEMORY_SIZE(memory);
-#endif
 #endif
 #endif
                 }
                 }
 
 

+ 31 - 11
core/iwasm/interpreter/wasm_loader.c

@@ -4862,7 +4862,6 @@ init_llvm_jit_functions_stage1(WASMModule *module, char *error_buf,
     option.opt_level = llvm_jit_options.opt_level;
     option.opt_level = llvm_jit_options.opt_level;
     option.size_level = llvm_jit_options.size_level;
     option.size_level = llvm_jit_options.size_level;
     option.segue_flags = llvm_jit_options.segue_flags;
     option.segue_flags = llvm_jit_options.segue_flags;
-    option.linux_perf_support = llvm_jit_options.linux_perf_support;
 
 
 #if WASM_ENABLE_BULK_MEMORY != 0
 #if WASM_ENABLE_BULK_MEMORY != 0
     option.enable_bulk_memory = true;
     option.enable_bulk_memory = true;
@@ -11278,13 +11277,33 @@ re_scan:
             {
             {
 #if WASM_ENABLE_GC == 0
 #if WASM_ENABLE_GC == 0
 #if WASM_ENABLE_FAST_INTERP != 0
 #if WASM_ENABLE_FAST_INTERP != 0
-                if (!wasm_loader_pop_frame_ref_offset(loader_ctx,
-                                                      VALUE_TYPE_FUNCREF,
-                                                      error_buf, error_buf_size)
-                    && !wasm_loader_pop_frame_ref_offset(
-                        loader_ctx, VALUE_TYPE_EXTERNREF, error_buf,
-                        error_buf_size)) {
-                    goto fail;
+                BranchBlock *cur_block = loader_ctx->frame_csp - 1;
+                int32 block_stack_cell_num =
+                    (int32)(loader_ctx->stack_cell_num
+                            - cur_block->stack_cell_num);
+                if (block_stack_cell_num <= 0) {
+                    if (!cur_block->is_stack_polymorphic) {
+                        set_error_buf(
+                            error_buf, error_buf_size,
+                            "type mismatch: expect data but stack was empty");
+                        goto fail;
+                    }
+                }
+                else {
+                    if (*(loader_ctx->frame_ref - 1) == VALUE_TYPE_FUNCREF
+                        || *(loader_ctx->frame_ref - 1) == VALUE_TYPE_EXTERNREF
+                        || *(loader_ctx->frame_ref - 1) == VALUE_TYPE_ANY) {
+                        if (!wasm_loader_pop_frame_ref_offset(
+                                loader_ctx, *(loader_ctx->frame_ref - 1),
+                                error_buf, error_buf_size)) {
+                            goto fail;
+                        }
+                    }
+                    else {
+                        set_error_buf(error_buf, error_buf_size,
+                                      "type mismatch");
+                        goto fail;
+                    }
                 }
                 }
 #else
 #else
                 if (!wasm_loader_pop_frame_ref(loader_ctx, VALUE_TYPE_FUNCREF,
                 if (!wasm_loader_pop_frame_ref(loader_ctx, VALUE_TYPE_FUNCREF,
@@ -11320,10 +11339,11 @@ re_scan:
                     bool func_declared = false;
                     bool func_declared = false;
                     uint32 j;
                     uint32 j;
 
 
-                    /* Check whether the function is declared in table segs */
+                    /* Check whether the function is declared in table segs,
+                       note that it doesn't matter whether the table seg's mode
+                       is passive, active or declarative. */
                     for (i = 0; i < module->table_seg_count; i++, table_seg++) {
                     for (i = 0; i < module->table_seg_count; i++, table_seg++) {
-                        if (table_seg->elem_type == VALUE_TYPE_FUNCREF
-                            && wasm_elem_is_declarative(table_seg->mode)) {
+                        if (table_seg->elem_type == VALUE_TYPE_FUNCREF) {
                             for (j = 0; j < table_seg->value_count; j++) {
                             for (j = 0; j < table_seg->value_count; j++) {
                                 if (table_seg->init_values[j].u.ref_index
                                 if (table_seg->init_values[j].u.ref_index
                                     == func_idx) {
                                     == func_idx) {

+ 31 - 11
core/iwasm/interpreter/wasm_mini_loader.c

@@ -2119,7 +2119,6 @@ init_llvm_jit_functions_stage1(WASMModule *module, char *error_buf,
     option.opt_level = llvm_jit_options.opt_level;
     option.opt_level = llvm_jit_options.opt_level;
     option.size_level = llvm_jit_options.size_level;
     option.size_level = llvm_jit_options.size_level;
     option.segue_flags = llvm_jit_options.segue_flags;
     option.segue_flags = llvm_jit_options.segue_flags;
-    option.linux_perf_support = llvm_jit_options.linux_perf_support;
 
 
 #if WASM_ENABLE_BULK_MEMORY != 0
 #if WASM_ENABLE_BULK_MEMORY != 0
     option.enable_bulk_memory = true;
     option.enable_bulk_memory = true;
@@ -6573,13 +6572,33 @@ re_scan:
             case WASM_OP_REF_IS_NULL:
             case WASM_OP_REF_IS_NULL:
             {
             {
 #if WASM_ENABLE_FAST_INTERP != 0
 #if WASM_ENABLE_FAST_INTERP != 0
-                if (!wasm_loader_pop_frame_ref_offset(loader_ctx,
-                                                      VALUE_TYPE_FUNCREF,
-                                                      error_buf, error_buf_size)
-                    && !wasm_loader_pop_frame_ref_offset(
-                        loader_ctx, VALUE_TYPE_EXTERNREF, error_buf,
-                        error_buf_size)) {
-                    goto fail;
+                BranchBlock *cur_block = loader_ctx->frame_csp - 1;
+                int32 block_stack_cell_num =
+                    (int32)(loader_ctx->stack_cell_num
+                            - cur_block->stack_cell_num);
+                if (block_stack_cell_num <= 0) {
+                    if (!cur_block->is_stack_polymorphic) {
+                        set_error_buf(
+                            error_buf, error_buf_size,
+                            "type mismatch: expect data but stack was empty");
+                        goto fail;
+                    }
+                }
+                else {
+                    if (*(loader_ctx->frame_ref - 1) == VALUE_TYPE_FUNCREF
+                        || *(loader_ctx->frame_ref - 1) == VALUE_TYPE_EXTERNREF
+                        || *(loader_ctx->frame_ref - 1) == VALUE_TYPE_ANY) {
+                        if (!wasm_loader_pop_frame_ref_offset(
+                                loader_ctx, *(loader_ctx->frame_ref - 1),
+                                error_buf, error_buf_size)) {
+                            goto fail;
+                        }
+                    }
+                    else {
+                        set_error_buf(error_buf, error_buf_size,
+                                      "type mismatch");
+                        goto fail;
+                    }
                 }
                 }
 #else
 #else
                 if (!wasm_loader_pop_frame_ref(loader_ctx, VALUE_TYPE_FUNCREF,
                 if (!wasm_loader_pop_frame_ref(loader_ctx, VALUE_TYPE_FUNCREF,
@@ -6609,10 +6628,11 @@ re_scan:
                     bool func_declared = false;
                     bool func_declared = false;
                     uint32 j;
                     uint32 j;
 
 
-                    /* Check whether the function is declared in table segs */
+                    /* Check whether the function is declared in table segs,
+                       note that it doesn't matter whether the table seg's mode
+                       is passive, active or declarative. */
                     for (i = 0; i < module->table_seg_count; i++, table_seg++) {
                     for (i = 0; i < module->table_seg_count; i++, table_seg++) {
-                        if (table_seg->elem_type == VALUE_TYPE_FUNCREF
-                            && wasm_elem_is_declarative(table_seg->mode)) {
+                        if (table_seg->elem_type == VALUE_TYPE_FUNCREF) {
                             for (j = 0; j < table_seg->value_count; j++) {
                             for (j = 0; j < table_seg->value_count; j++) {
                                 if (table_seg->init_values[j].u.ref_index
                                 if (table_seg->init_values[j].u.ref_index
                                     == func_idx) {
                                     == func_idx) {

+ 23 - 12
core/iwasm/interpreter/wasm_runtime.c

@@ -2918,7 +2918,6 @@ wasm_lookup_table(const WASMModuleInstance *module_inst, const char *name)
 #endif
 #endif
 
 
 #ifdef OS_ENABLE_HW_BOUND_CHECK
 #ifdef OS_ENABLE_HW_BOUND_CHECK
-
 static void
 static void
 call_wasm_with_hw_bound_check(WASMModuleInstance *module_inst,
 call_wasm_with_hw_bound_check(WASMModuleInstance *module_inst,
                               WASMExecEnv *exec_env,
                               WASMExecEnv *exec_env,
@@ -2948,19 +2947,26 @@ call_wasm_with_hw_bound_check(WASMModuleInstance *module_inst,
         return;
         return;
     }
     }
 
 
-    if (exec_env_tls && (exec_env_tls != exec_env)) {
-        wasm_set_exception(module_inst, "invalid exec env");
-        return;
-    }
+    if (!exec_env_tls) {
+        if (!os_thread_signal_inited()) {
+            wasm_set_exception(module_inst, "thread signal env not inited");
+            return;
+        }
 
 
-    if (!os_thread_signal_inited()) {
-        wasm_set_exception(module_inst, "thread signal env not inited");
-        return;
+        /* Set thread handle and stack boundary if they haven't been set */
+        wasm_exec_env_set_thread_info(exec_env);
+
+        wasm_runtime_set_exec_env_tls(exec_env);
+    }
+    else {
+        if (exec_env_tls != exec_env) {
+            wasm_set_exception(module_inst, "invalid exec env");
+            return;
+        }
     }
     }
 
 
     wasm_exec_env_push_jmpbuf(exec_env, &jmpbuf_node);
     wasm_exec_env_push_jmpbuf(exec_env, &jmpbuf_node);
 
 
-    wasm_runtime_set_exec_env_tls(exec_env);
     if (os_setjmp(jmpbuf_node.jmpbuf) == 0) {
     if (os_setjmp(jmpbuf_node.jmpbuf) == 0) {
 #ifndef BH_PLATFORM_WINDOWS
 #ifndef BH_PLATFORM_WINDOWS
         wasm_interp_call_wasm(module_inst, exec_env, function, argc, argv);
         wasm_interp_call_wasm(module_inst, exec_env, function, argc, argv);
@@ -2970,7 +2976,7 @@ call_wasm_with_hw_bound_check(WASMModuleInstance *module_inst,
         } __except (wasm_copy_exception(module_inst, NULL)
         } __except (wasm_copy_exception(module_inst, NULL)
                         ? EXCEPTION_EXECUTE_HANDLER
                         ? EXCEPTION_EXECUTE_HANDLER
                         : EXCEPTION_CONTINUE_SEARCH) {
                         : EXCEPTION_CONTINUE_SEARCH) {
-            /* exception was thrown in wasm_exception_handler */
+            /* Exception was thrown in wasm_exception_handler */
             ret = false;
             ret = false;
         }
         }
         has_exception = wasm_copy_exception(module_inst, exception);
         has_exception = wasm_copy_exception(module_inst, exception);
@@ -3024,10 +3030,15 @@ wasm_call_function(WASMExecEnv *exec_env, WASMFunctionInstance *function,
     WASMModuleInstance *module_inst =
     WASMModuleInstance *module_inst =
         (WASMModuleInstance *)exec_env->module_inst;
         (WASMModuleInstance *)exec_env->module_inst;
 
 
-    /* set thread handle and stack boundary */
+#ifndef OS_ENABLE_HW_BOUND_CHECK
+    /* Set thread handle and stack boundary */
     wasm_exec_env_set_thread_info(exec_env);
     wasm_exec_env_set_thread_info(exec_env);
+#else
+    /* Set thread info in call_wasm_with_hw_bound_check when
+       hw bound check is enabled */
+#endif
 
 
-    /* set exec env so it can be later retrieved from instance */
+    /* Set exec env so it can be later retrieved from instance */
     module_inst->e->common.cur_exec_env = exec_env;
     module_inst->e->common.cur_exec_env = exec_env;
 
 
     interp_call_wasm(module_inst, exec_env, function, argc, argv);
     interp_call_wasm(module_inst, exec_env, function, argc, argv);

+ 46 - 1
core/shared/platform/common/freertos/freertos_thread.c

@@ -205,7 +205,6 @@ os_thread_wrapper(void *arg)
 
 
     thread_data->start_routine(thread_data->arg);
     thread_data->start_routine(thread_data->arg);
     os_thread_cleanup();
     os_thread_cleanup();
-    vTaskDelete(NULL);
 }
 }
 
 
 int
 int
@@ -301,6 +300,22 @@ os_thread_join(korp_tid thread, void **value_ptr)
     return BHT_OK;
     return BHT_OK;
 }
 }
 
 
+int
+os_thread_detach(korp_tid thread)
+{
+    /* Do nothing */
+    (void)thread;
+    return BHT_OK;
+}
+
+void
+os_thread_exit(void *retval)
+{
+    (void)retval;
+    os_thread_cleanup();
+    vTaskDelete(NULL);
+}
+
 int
 int
 os_mutex_init(korp_mutex *mutex)
 os_mutex_init(korp_mutex *mutex)
 {
 {
@@ -452,3 +467,33 @@ os_cond_signal(korp_cond *cond)
 
 
     return BHT_OK;
     return BHT_OK;
 }
 }
+
+int
+os_cond_broadcast(korp_cond *cond)
+{
+    /* Signal all of the wait node of wait list */
+    xSemaphoreTake(cond->wait_list_lock, portMAX_DELAY);
+    if (cond->thread_wait_list) {
+        os_thread_wait_node *p = cond->thread_wait_list;
+        while (p) {
+            xSemaphoreGive(p->sem);
+            p = p->next;
+        }
+    }
+    xSemaphoreGive(cond->wait_list_lock);
+
+    return BHT_OK;
+}
+
+uint8 *
+os_thread_get_stack_boundary()
+{
+    /* TODO: get freertos stack boundary */
+    return NULL;
+}
+
+void
+os_thread_jit_write_protect_np(bool enabled)
+{
+    (void)enabled;
+}

+ 2 - 0
core/shared/utils/bh_log.c

@@ -43,7 +43,9 @@ bh_log(LogLevel log_level, const char *file, int line, const char *fmt, ...)
              "%02" PRIu32 ":%02" PRIu32 ":%02" PRIu32 ":%03" PRIu32, h, m, s,
              "%02" PRIu32 ":%02" PRIu32 ":%02" PRIu32 ":%03" PRIu32, h, m, s,
              mills);
              mills);
 
 
+#ifndef BH_VPRINTF
     os_printf("[%s - %" PRIXPTR "]: ", buf, (uintptr_t)self);
     os_printf("[%s - %" PRIXPTR "]: ", buf, (uintptr_t)self);
+#endif
 
 
     if (file)
     if (file)
         os_printf("%s, line %d, ", file, line);
         os_printf("%s, line %d, ", file, line);

+ 14 - 1
doc/perf_tune.md

@@ -134,7 +134,7 @@ $ perf report --input=perf.data
 >
 >
 > For example, with EMCC, you can add `-g2`.
 > For example, with EMCC, you can add `-g2`.
 >
 >
-> If not able to get the context of the custom name section, WAMR will use `aot_func#N` to represent the function name. `N` is from 0. `aot_func#0` represents the first *not imported wasm function*.
+> If not able to get the context of the custom name section, WAMR will use `aot_func#N` to represent the function name. `N` is from 0. `aot_func#0` represents the first _not imported wasm function_.
 
 
 ### 7.1 Flamegraph
 ### 7.1 Flamegraph
 
 
@@ -177,3 +177,16 @@ $ ./FlameGraph/flamegraph.pl out.folded > perf.foo.wasm.svg
 > # only jitted functions
 > # only jitted functions
 > $ grep "wasm_runtime_invoke_native" out.folded | ./FlameGraph/flamegraph.pl > perf.foo.wasm.only.svg
 > $ grep "wasm_runtime_invoke_native" out.folded | ./FlameGraph/flamegraph.pl > perf.foo.wasm.only.svg
 > ```
 > ```
+
+> [!TIP]
+> use [trans_wasm_func_name.py](../test-tools/trans-jitted-func-name/trans_wasm_func_name.py) to translate jitted function
+> names to its original wasm function names. It requires _wasm-objdump_ in _wabt_ and _name section_ in the .wasm file
+>
+> The input file is the output of `./FlameGraph/stackcollapse-perf.pl`.
+>
+> ```bash
+> python trans_wasm_func_name.py --wabt_home <wabt-installation> --folded out.folded <.wasm>
+> ```
+>
+> Then you will see a new file named _out.folded.translated_ which contains the translated folded stacks.
+> All wasm functions are translated to its original names with a prefix like "[Wasm]"

+ 2 - 206
doc/source_debugging.md

@@ -1,13 +1,5 @@
 # WAMR source debugging
 # WAMR source debugging
 
 
-References:
-- [Blog: WAMR source debugging basic](https://bytecodealliance.github.io/wamr.dev/blog/wamr-source-debugging-basic/)  
-- [Blog: Debugging wasm with VSCode](https://bytecodealliance.github.io/wamr.dev/blog/debugging-wasm-with-vscode/)
-
-WAMR supports source level debugging based on DWARF (normally used in C/C++/Rust), source map (normally used in AssemblyScript) is not supported.
-
-**The lldb's ability to debug wasm application is based on the patch [Add class WasmProcess for WebAssembly debugging](https://reviews.llvm.org/D78801). Thanks very much to the author @paolosev for such a great work!**
-
 ## Build wasm application with debug information
 ## Build wasm application with debug information
 To debug your application, you need to compile them with debug information. You can use `-g` option when compiling the source code if you are using wasi-sdk (also work for emcc and rustc):
 To debug your application, you need to compile them with debug information. You can use `-g` option when compiling the source code if you are using wasi-sdk (also work for emcc and rustc):
 ``` bash
 ``` bash
@@ -20,205 +12,9 @@ llvm-dwarfdump-12 test.wasm
 ```
 ```
 
 
 ## Debugging with interpreter
 ## Debugging with interpreter
-1. Install dependent libraries
-``` bash
-apt update && apt install cmake make g++ libxml2-dev -y
-```
-
-2. Build iwasm with source debugging feature
-``` bash
-cd ${WAMR_ROOT}/product-mini/platforms/linux
-mkdir build && cd build
-cmake .. -DWAMR_BUILD_DEBUG_INTERP=1
-make
-```
-> Note: On MacOS M1 environment, pass the additional `-DWAMR_DISABLE_HW_BOUND_CHECK=1` cmake configuration.
-
-3. Execute iwasm with debug engine enabled
-``` bash
-iwasm -g=127.0.0.1:1234 test.wasm
-# Use port = 0 to allow a random assigned debug port
-```
-
-4. Build customized lldb
-``` bash
-git clone --branch release/13.x --depth=1 https://github.com/llvm/llvm-project
-cd llvm-project
-git apply ${WAMR_ROOT}/build-scripts/lldb_wasm.patch
-mkdir build-lldb
-cmake -S ./llvm -B build-lldb \
-    -G Ninja \
-    -DCMAKE_BUILD_TYPE=Release -DLLVM_ENABLE_PROJECTS="clang;lldb" \
-    -DLLVM_TARGETS_TO_BUILD:STRING="X86;WebAssembly" \
-    -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DLLVM_BUILD_BENCHMARKS:BOOL=OFF \
-    -DLLVM_BUILD_DOCS:BOOL=OFF  -DLLVM_BUILD_EXAMPLES:BOOL=OFF  \
-    -DLLVM_BUILD_LLVM_DYLIB:BOOL=OFF  -DLLVM_BUILD_TESTS:BOOL=OFF  \
-    -DLLVM_ENABLE_BINDINGS:BOOL=OFF  -DLLVM_INCLUDE_BENCHMARKS:BOOL=OFF  \
-    -DLLVM_INCLUDE_DOCS:BOOL=OFF  -DLLVM_INCLUDE_EXAMPLES:BOOL=OFF  \
-    -DLLVM_INCLUDE_TESTS:BOOL=OFF -DLLVM_ENABLE_LIBXML2:BOOL=ON
-cmake --build build-lldb --target lldb --parallel $(nproc)
-# The lldb is generated under build-lldb/bin/lldb
-```
-> Note: If using `CommandLineTools` on MacOS, make sure only one SDK is present in `/Library/Developer/CommandLineTools/SDKs`.
-
-> You can download pre-built `wamr-lldb` binaries from [here](https://github.com/bytecodealliance/wasm-micro-runtime/releases).
 
 
-5. Launch customized lldb and connect to iwasm
-``` bash
-lldb
-(lldb) process connect -p wasm connect://127.0.0.1:1234
-```
-Then you can use lldb commands to debug your applications. Please refer to [lldb document](https://lldb.llvm.org/use/tutorial.html) for command usage.
+See [Debuggging with interpreter](source_debugging_interpreter.md).
 
 
 ## Debugging with AOT
 ## Debugging with AOT
 
 
-> Note: AOT debugging is experimental and only a few debugging capabilities are supported.
-
-1. Build lldb (assume you have already built llvm)
-``` bash
-cd ${WAMR_ROOT}/core/deps/llvm/build
-cmake ../llvm -DLLVM_ENABLE_PROJECTS="clang;lldb" -DLLDB_INCLUDE_TESTS=OFF
-make -j $(nproc)
-```
-
-2. Build wamrc with debugging feature
-``` bash
-cd ${WAMR_ROOT}/wamr-compiler
-mkdir build && cd build
-cmake .. -DWAMR_BUILD_DEBUG_AOT=1
-make -j $(nproc)
-```
-
-3. Build iwasm with debugging feature
-``` bash
-cd ${WAMR_ROOT}/product-mini/platforms/linux
-mkdir build && cd build
-cmake .. -DWAMR_BUILD_DEBUG_AOT=1
-make
-```
-
-4. Compile wasm module to AOT module
-``` bash
-wamrc -o test.aot test.wasm
-```
-
-5. Execute iwasm using lldb
-
-   Then you can use lldb commands to debug both wamr runtime and your wasm application in ***current terminal***.
-
-   ``` bash
-   % lldb iwasm -- test.aot
-   (lldb) target create "iwasm"
-   Current executable set to 'iwasm' (x86_64).
-   (lldb) settings set -- target.run-args  "test.aot"
-   (lldb) settings set plugin.jit-loader.gdb.enable on
-   (lldb) b main
-   Breakpoint 1: where = iwasm`main + 48 at main.c:294:11, address = 0x0000000100001020
-   (lldb) run
-   Process 27954 launched: '/tmp/bin/iwasm' (x86_64)
-   Process 27954 stopped
-   * thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
-       frame #0: 0x0000000100001020 iwasm`main(argc=2, argv=0x00007ff7bfeff678) at main.c:294:11
-      291  int
-      292  main(int argc, char *argv[])
-      293  {
-   -> 294      int32 ret = -1;
-      295      char *wasm_file = NULL;
-      296      const char *func_name = NULL;
-      297      uint8 *wasm_file_buf = NULL;
-   Target 0: (iwasm) stopped.
-   (lldb) c
-   Process 27954 resuming
-   1 location added to breakpoint 1
-   error: need to add support for DW_TAG_base_type 'void' encoded with DW_ATE = 0x0, bit_size = 0
-   Process 27954 stopped
-   * thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.2
-       frame #0: 0x00000001002980a0 JIT(0x100298004)`main(exenv=0x0000000301808200) at hello.c:6:9
-      3    int
-      4    main(void)
-      5    {
-   -> 6            printf("hello\n");
-      7
-      8            return 0;
-      9    }
-   Target 0: (iwasm) stopped.
-   (lldb) br l
-   Current breakpoints:
-   1: name = 'main', locations = 2, resolved = 2, hit count = 2
-     1.1: where = iwasm`main + 48 at main.c:294:11, address = 0x0000000100001020, resolved, hit count = 1
-     1.2: where = JIT(0x100298004)`main + 12 at hello.c:6:9, address = 0x00000001002980a0, resolved, hit count = 1
-
-   (lldb)
-   ```
-
-   * In the above example,
-
-     * The first `main` function, which is in `main.c`, is the main
-       function of the iwasm command.
-
-     * The second `main` function, which is in `hello.c`, is the main
-       function of the AOT-compiled wasm module.
-
-   * WAMR AOT debugging uses the GDB JIT loader mechanism to load
-     the debug info of the debugee module.
-     On some platforms including macOS, you need to enable it explicitly.
-     (`settings set plugin.jit-loader.gdb.enable on`)
-
-     References:
-
-     * https://github.com/llvm/llvm-project/blob/main/llvm/docs/DebuggingJITedCode.rst
-     * https://sourceware.org/gdb/current/onlinedocs/gdb/JIT-Interface.html
-
-## Enable debugging in embedders (for interpreter)
-
-There are three steps to enable debugging in embedders
-
-1. Set the debug parameters when initializing the runtime environment:
-    ``` c
-    RuntimeInitArgs init_args;
-    memset(&init_args, 0, sizeof(RuntimeInitArgs));
-
-    /* ... */
-    strcpy(init_args.ip_addr, "127.0.0.1");
-    init_args.instance_port = 1234;
-    /*
-    * Or set port to 0 to use a port assigned by os
-    * init_args.instance_port = 0;
-    */
-
-    if (!wasm_runtime_full_init(&init_args)) {
-        return false;
-    }
-    ```
-
-2. Use `wasm_runtime_start_debug_instance` to create the debug instance:
-    ``` c
-    /*
-        initialization, loading and instantiating
-        ...
-    */
-    exec_env = wasm_runtime_create_exec_env(module_inst, stack_size);
-    uint32_t debug_port = wasm_runtime_start_debug_instance(exec_env);
-    ```
-
-3. Enable source debugging features during building
-
-    You can use `-DWAMR_BUILD_DEBUG_INTERP=1` during cmake configuration
-
-    Or you can set it directly in `cmake` files:
-    ``` cmake
-    set (WAMR_BUILD_DEBUG_INTERP 1)
-    ```
-
-### Attentions
-- Debugging `multi-thread wasm module` is not supported, if your wasm module use pthread APIs (see [pthread_library.md](./pthread_library.md)), or the embedder use `wasm_runtime_spawn_thread` to create new wasm threads, then there may be **unexpected behaviour** during debugging.
-
-    > Note: This attention is about "wasm thread" rather than native threads. Executing wasm functions in several different native threads will **not** affect the normal behaviour of debugging feature.
-
-- When using source debugging features, **don't** create multiple `wasm_instance` from the same `wasm_module`, because the debugger may change the bytecode (set/unset breakpoints) of the `wasm_module`. If you do need several instance from the same bytecode, you need to copy the bytecode to a new butter, then load a new `wasm_module`, and then instantiate the new wasm module to get the new instance.
-
-- If you are running `lldb` on non-linux platforms, please use `platform select remote-linux` command in lldb before connecting to the runtime:
-    ```
-    (lldb) platform select remote-linux
-    (lldb) process connect -p wasm connect://127.0.0.1:1234
-    ```
+See [Debuggging with AOT](source_debugging_aot.md).

+ 100 - 0
doc/source_debugging_aot.md

@@ -0,0 +1,100 @@
+# WAMR source debugging (AOT)
+
+## Debugging with AOT
+
+> Note: AOT debugging is experimental and only a few debugging capabilities are supported.
+
+1. Build lldb (assume you have already built llvm)
+``` bash
+cd ${WAMR_ROOT}/core/deps/llvm/build
+cmake ../llvm -DLLVM_ENABLE_PROJECTS="clang;lldb" -DLLDB_INCLUDE_TESTS=OFF
+make -j $(nproc)
+```
+
+2. Build wamrc with debugging feature
+``` bash
+cd ${WAMR_ROOT}/wamr-compiler
+mkdir build && cd build
+cmake .. -DWAMR_BUILD_DEBUG_AOT=1
+make -j $(nproc)
+```
+
+3. Build iwasm with debugging feature
+``` bash
+cd ${WAMR_ROOT}/product-mini/platforms/linux
+mkdir build && cd build
+cmake .. -DWAMR_BUILD_DEBUG_AOT=1
+make
+```
+
+4. Compile wasm module to AOT module
+``` bash
+wamrc -o test.aot test.wasm
+```
+
+5. Execute iwasm using lldb
+
+   Then you can use lldb commands to debug both wamr runtime and your wasm application in ***current terminal***.
+
+   ``` bash
+   % lldb iwasm -- test.aot
+   (lldb) target create "iwasm"
+   Current executable set to 'iwasm' (x86_64).
+   (lldb) settings set -- target.run-args  "test.aot"
+   (lldb) settings set plugin.jit-loader.gdb.enable on
+   (lldb) b main
+   Breakpoint 1: where = iwasm`main + 48 at main.c:294:11, address = 0x0000000100001020
+   (lldb) run
+   Process 27954 launched: '/tmp/bin/iwasm' (x86_64)
+   Process 27954 stopped
+   * thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
+       frame #0: 0x0000000100001020 iwasm`main(argc=2, argv=0x00007ff7bfeff678) at main.c:294:11
+      291  int
+      292  main(int argc, char *argv[])
+      293  {
+   -> 294      int32 ret = -1;
+      295      char *wasm_file = NULL;
+      296      const char *func_name = NULL;
+      297      uint8 *wasm_file_buf = NULL;
+   Target 0: (iwasm) stopped.
+   (lldb) c
+   Process 27954 resuming
+   1 location added to breakpoint 1
+   error: need to add support for DW_TAG_base_type 'void' encoded with DW_ATE = 0x0, bit_size = 0
+   Process 27954 stopped
+   * thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.2
+       frame #0: 0x00000001002980a0 JIT(0x100298004)`main(exenv=0x0000000301808200) at hello.c:6:9
+      3    int
+      4    main(void)
+      5    {
+   -> 6            printf("hello\n");
+      7
+      8            return 0;
+      9    }
+   Target 0: (iwasm) stopped.
+   (lldb) br l
+   Current breakpoints:
+   1: name = 'main', locations = 2, resolved = 2, hit count = 2
+     1.1: where = iwasm`main + 48 at main.c:294:11, address = 0x0000000100001020, resolved, hit count = 1
+     1.2: where = JIT(0x100298004)`main + 12 at hello.c:6:9, address = 0x00000001002980a0, resolved, hit count = 1
+
+   (lldb)
+   ```
+
+   * In the above example,
+
+     * The first `main` function, which is in `main.c`, is the main
+       function of the iwasm command.
+
+     * The second `main` function, which is in `hello.c`, is the main
+       function of the AOT-compiled wasm module.
+
+   * WAMR AOT debugging uses the GDB JIT loader mechanism to load
+     the debug info of the debugee module.
+     On some platforms including macOS, you need to enable it explicitly.
+     (`settings set plugin.jit-loader.gdb.enable on`)
+
+     References:
+
+     * https://github.com/llvm/llvm-project/blob/main/llvm/docs/DebuggingJITedCode.rst
+     * https://sourceware.org/gdb/current/onlinedocs/gdb/JIT-Interface.html

+ 115 - 0
doc/source_debugging_interpreter.md

@@ -0,0 +1,115 @@
+# WAMR source debugging (interpreter)
+
+References:
+- [Blog: WAMR source debugging basic](https://bytecodealliance.github.io/wamr.dev/blog/wamr-source-debugging-basic/)  
+- [Blog: Debugging wasm with VSCode](https://bytecodealliance.github.io/wamr.dev/blog/debugging-wasm-with-vscode/)
+
+WAMR supports source level debugging based on DWARF (normally used in C/C++/Rust), source map (normally used in AssemblyScript) is not supported.
+
+**The lldb's ability to debug wasm application is based on the patch [Add class WasmProcess for WebAssembly debugging](https://reviews.llvm.org/D78801). Thanks very much to the author @paolosev for such a great work!**
+
+## Debugging with interpreter
+
+1. Install dependent libraries
+``` bash
+apt update && apt install cmake make g++ libxml2-dev -y
+```
+
+2. Build iwasm with source debugging feature
+``` bash
+cd ${WAMR_ROOT}/product-mini/platforms/linux
+mkdir build && cd build
+cmake .. -DWAMR_BUILD_DEBUG_INTERP=1
+make
+```
+> Note: On MacOS M1 environment, pass the additional `-DWAMR_DISABLE_HW_BOUND_CHECK=1` cmake configuration.
+
+3. Execute iwasm with debug engine enabled
+``` bash
+iwasm -g=127.0.0.1:1234 test.wasm
+# Use port = 0 to allow a random assigned debug port
+```
+
+4. Build customized lldb
+``` bash
+git clone --branch release/13.x --depth=1 https://github.com/llvm/llvm-project
+cd llvm-project
+git apply ${WAMR_ROOT}/build-scripts/lldb_wasm.patch
+mkdir build-lldb
+cmake -S ./llvm -B build-lldb \
+    -G Ninja \
+    -DCMAKE_BUILD_TYPE=Release -DLLVM_ENABLE_PROJECTS="clang;lldb" \
+    -DLLVM_TARGETS_TO_BUILD:STRING="X86;WebAssembly" \
+    -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DLLVM_BUILD_BENCHMARKS:BOOL=OFF \
+    -DLLVM_BUILD_DOCS:BOOL=OFF  -DLLVM_BUILD_EXAMPLES:BOOL=OFF  \
+    -DLLVM_BUILD_LLVM_DYLIB:BOOL=OFF  -DLLVM_BUILD_TESTS:BOOL=OFF  \
+    -DLLVM_ENABLE_BINDINGS:BOOL=OFF  -DLLVM_INCLUDE_BENCHMARKS:BOOL=OFF  \
+    -DLLVM_INCLUDE_DOCS:BOOL=OFF  -DLLVM_INCLUDE_EXAMPLES:BOOL=OFF  \
+    -DLLVM_INCLUDE_TESTS:BOOL=OFF -DLLVM_ENABLE_LIBXML2:BOOL=ON
+cmake --build build-lldb --target lldb --parallel $(nproc)
+# The lldb is generated under build-lldb/bin/lldb
+```
+> Note: If using `CommandLineTools` on MacOS, make sure only one SDK is present in `/Library/Developer/CommandLineTools/SDKs`.
+
+> You can download pre-built `wamr-lldb` binaries from [here](https://github.com/bytecodealliance/wasm-micro-runtime/releases).
+
+5. Launch customized lldb and connect to iwasm
+``` bash
+lldb
+(lldb) process connect -p wasm connect://127.0.0.1:1234
+```
+Then you can use lldb commands to debug your applications. Please refer to [lldb document](https://lldb.llvm.org/use/tutorial.html) for command usage.
+
+## Enable debugging in embedders (for interpreter)
+
+There are three steps to enable debugging in embedders
+
+1. Set the debug parameters when initializing the runtime environment:
+    ``` c
+    RuntimeInitArgs init_args;
+    memset(&init_args, 0, sizeof(RuntimeInitArgs));
+
+    /* ... */
+    strcpy(init_args.ip_addr, "127.0.0.1");
+    init_args.instance_port = 1234;
+    /*
+    * Or set port to 0 to use a port assigned by os
+    * init_args.instance_port = 0;
+    */
+
+    if (!wasm_runtime_full_init(&init_args)) {
+        return false;
+    }
+    ```
+
+2. Use `wasm_runtime_start_debug_instance` to create the debug instance:
+    ``` c
+    /*
+        initialization, loading and instantiating
+        ...
+    */
+    exec_env = wasm_runtime_create_exec_env(module_inst, stack_size);
+    uint32_t debug_port = wasm_runtime_start_debug_instance(exec_env);
+    ```
+
+3. Enable source debugging features during building
+
+    You can use `-DWAMR_BUILD_DEBUG_INTERP=1` during cmake configuration
+
+    Or you can set it directly in `cmake` files:
+    ``` cmake
+    set (WAMR_BUILD_DEBUG_INTERP 1)
+    ```
+
+### Attentions
+- Debugging `multi-thread wasm module` is not supported, if your wasm module use pthread APIs (see [pthread_library.md](./pthread_library.md)), or the embedder use `wasm_runtime_spawn_thread` to create new wasm threads, then there may be **unexpected behaviour** during debugging.
+
+    > Note: This attention is about "wasm thread" rather than native threads. Executing wasm functions in several different native threads will **not** affect the normal behaviour of debugging feature.
+
+- When using source debugging features, **don't** create multiple `wasm_instance` from the same `wasm_module`, because the debugger may change the bytecode (set/unset breakpoints) of the `wasm_module`. If you do need several instance from the same bytecode, you need to copy the bytecode to a new butter, then load a new `wasm_module`, and then instantiate the new wasm module to get the new instance.
+
+- If you are running `lldb` on non-linux platforms, please use `platform select remote-linux` command in lldb before connecting to the runtime:
+    ```
+    (lldb) platform select remote-linux
+    (lldb) process connect -p wasm connect://127.0.0.1:1234
+    ```

+ 6 - 0
product-mini/platforms/nuttx/wamr.mk

@@ -133,6 +133,11 @@ CSRCS += aot_loader.c \
          $(AOT_RELOC) \
          $(AOT_RELOC) \
          aot_intrinsic.c \
          aot_intrinsic.c \
          aot_runtime.c
          aot_runtime.c
+ifeq ($(CONFIG_INTERPRETERS_WAMR_DEBUG_AOT),y)
+CFLAGS += -DWASM_ENABLE_DEBUG_AOT=1
+CSRCS += elf_parser.c \
+         jit_debug.c
+endif
 else
 else
 CFLAGS += -DWASM_ENABLE_AOT=0
 CFLAGS += -DWASM_ENABLE_AOT=0
 endif
 endif
@@ -441,3 +446,4 @@ VPATH += $(IWASM_ROOT)/libraries/lib-pthread
 VPATH += $(IWASM_ROOT)/common/arch
 VPATH += $(IWASM_ROOT)/common/arch
 VPATH += $(IWASM_ROOT)/aot
 VPATH += $(IWASM_ROOT)/aot
 VPATH += $(IWASM_ROOT)/aot/arch
 VPATH += $(IWASM_ROOT)/aot/arch
+VPATH += $(IWASM_ROOT)/aot/debug

+ 14 - 6
product-mini/platforms/posix/main.c

@@ -62,7 +62,6 @@ print_help()
 #if WASM_ENABLE_JIT != 0
 #if WASM_ENABLE_JIT != 0
     printf("  --llvm-jit-size-level=n  Set LLVM JIT size level, default is 3\n");
     printf("  --llvm-jit-size-level=n  Set LLVM JIT size level, default is 3\n");
     printf("  --llvm-jit-opt-level=n   Set LLVM JIT optimization level, default is 3\n");
     printf("  --llvm-jit-opt-level=n   Set LLVM JIT optimization level, default is 3\n");
-    printf("  --perf-profile           Enable linux perf support. For now, it only works in llvm-jit.\n");
 #if defined(os_writegsbase)
 #if defined(os_writegsbase)
     printf("  --enable-segue[=<flags>] Enable using segment register GS as the base address of\n");
     printf("  --enable-segue[=<flags>] Enable using segment register GS as the base address of\n");
     printf("                           linear memory, which may improve performance, flags can be:\n");
     printf("                           linear memory, which may improve performance, flags can be:\n");
@@ -71,6 +70,9 @@ print_help()
     printf("                           Use comma to separate, e.g. --enable-segue=i32.load,i64.store\n");
     printf("                           Use comma to separate, e.g. --enable-segue=i32.load,i64.store\n");
     printf("                           and --enable-segue means all flags are added.\n");
     printf("                           and --enable-segue means all flags are added.\n");
 #endif
 #endif
+#endif /* WASM_ENABLE_JIT != 0*/
+#if WASM_ENABLE_LINUX_PERF != 0
+    printf("  --enable-linux-perf      Enable linux perf support. It works in aot and llvm-jit.\n");
 #endif
 #endif
     printf("  --repl                   Start a very simple REPL (read-eval-print-loop) mode\n"
     printf("  --repl                   Start a very simple REPL (read-eval-print-loop) mode\n"
            "                           that runs commands in the form of \"FUNC ARG...\"\n");
            "                           that runs commands in the form of \"FUNC ARG...\"\n");
@@ -568,7 +570,9 @@ main(int argc, char *argv[])
     uint32 llvm_jit_size_level = 3;
     uint32 llvm_jit_size_level = 3;
     uint32 llvm_jit_opt_level = 3;
     uint32 llvm_jit_opt_level = 3;
     uint32 segue_flags = 0;
     uint32 segue_flags = 0;
-    bool enable_linux_perf_support = false;
+#endif
+#if WASM_ENABLE_LINUX_PERF != 0
+    bool enable_linux_perf = false;
 #endif
 #endif
     wasm_module_t wasm_module = NULL;
     wasm_module_t wasm_module = NULL;
     wasm_module_inst_t wasm_module_inst = NULL;
     wasm_module_inst_t wasm_module_inst = NULL;
@@ -716,9 +720,6 @@ main(int argc, char *argv[])
             if (segue_flags == (uint32)-1)
             if (segue_flags == (uint32)-1)
                 return print_help();
                 return print_help();
         }
         }
-        else if (!strncmp(argv[0], "--perf-profile", 14)) {
-            enable_linux_perf_support = true;
-        }
 #endif /* end of WASM_ENABLE_JIT != 0 */
 #endif /* end of WASM_ENABLE_JIT != 0 */
 #if BH_HAS_DLFCN
 #if BH_HAS_DLFCN
         else if (!strncmp(argv[0], "--native-lib=", 13)) {
         else if (!strncmp(argv[0], "--native-lib=", 13)) {
@@ -732,6 +733,11 @@ main(int argc, char *argv[])
             native_lib_list[native_lib_count++] = argv[0] + 13;
             native_lib_list[native_lib_count++] = argv[0] + 13;
         }
         }
 #endif
 #endif
+#if WASM_ENABLE_LINUX_PERF != 0
+        else if (!strncmp(argv[0], "--enable-linux-perf", 19)) {
+            enable_linux_perf = true;
+        }
+#endif
 #if WASM_ENABLE_MULTI_MODULE != 0
 #if WASM_ENABLE_MULTI_MODULE != 0
         else if (!strncmp(argv[0],
         else if (!strncmp(argv[0],
                           "--module-path=", strlen("--module-path="))) {
                           "--module-path=", strlen("--module-path="))) {
@@ -837,7 +843,9 @@ main(int argc, char *argv[])
     init_args.llvm_jit_size_level = llvm_jit_size_level;
     init_args.llvm_jit_size_level = llvm_jit_size_level;
     init_args.llvm_jit_opt_level = llvm_jit_opt_level;
     init_args.llvm_jit_opt_level = llvm_jit_opt_level;
     init_args.segue_flags = segue_flags;
     init_args.segue_flags = segue_flags;
-    init_args.linux_perf_support = enable_linux_perf_support;
+#endif
+#if WASM_ENABLE_LINUX_PERF != 0
+    init_args.enable_linux_perf = enable_linux_perf;
 #endif
 #endif
 
 
 #if WASM_ENABLE_DEBUG_INTERP != 0
 #if WASM_ENABLE_DEBUG_INTERP != 0

+ 1 - 0
samples/sgx-ra/CMakeLists.txt

@@ -69,6 +69,7 @@ execute_process (
 add_custom_target (
 add_custom_target (
               iwasm ALL
               iwasm ALL
               DEPENDS vmlib_untrusted vmlib_untrusted vmlib
               DEPENDS vmlib_untrusted vmlib_untrusted vmlib
+              COMMAND make -C ${SGX_PLATFORM_DIR}/enclave-sample clean
               COMMAND make -C  ${SGX_PLATFORM_DIR}/enclave-sample SGX_MODE=HW SGX_DEBUG=1 VMLIB_BUILD_DIR=${CMAKE_BINARY_DIR}
               COMMAND make -C  ${SGX_PLATFORM_DIR}/enclave-sample SGX_MODE=HW SGX_DEBUG=1 VMLIB_BUILD_DIR=${CMAKE_BINARY_DIR}
               COMMAND ${CMAKE_COMMAND} -E copy ${SGX_PLATFORM_DIR}/enclave-sample/enclave.signed.so ${CMAKE_BINARY_DIR}
               COMMAND ${CMAKE_COMMAND} -E copy ${SGX_PLATFORM_DIR}/enclave-sample/enclave.signed.so ${CMAKE_BINARY_DIR}
               COMMAND ${CMAKE_COMMAND} -E copy ${SGX_PLATFORM_DIR}/enclave-sample/iwasm ${CMAKE_BINARY_DIR}
               COMMAND ${CMAKE_COMMAND} -E copy ${SGX_PLATFORM_DIR}/enclave-sample/iwasm ${CMAKE_BINARY_DIR}

+ 161 - 0
test-tools/append-aot-to-wasm/append_aot_to_wasm.py

@@ -0,0 +1,161 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2019 Intel Corporation.  All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+#
+"""
+It is used to append a .aot to a .wasm as a custom section.
+The custom section name is "aot".
+
+e.g.
+$ python3 append_aot_to_wasm.py --wasm quicksort.wasm --aot quicksort.aot --output quicksort.aot.wasm
+"""
+
+import argparse
+from pathlib import Path
+
+
+def leb128_encode_uint(value: int) -> bytes:
+    """
+    encode unsigned int into a leb128 bytes
+    """
+    binary = []
+    while value != 0:
+        lower_7_bits = value & 0x7F
+        value >>= 7
+
+        if value != 0:
+            current_byte = 0x80 | lower_7_bits
+        else:
+            current_byte = 0x00 | lower_7_bits
+
+        binary.append(current_byte)
+
+    return bytes(binary)
+
+
+def leb128_decode_uint(binary: bytes) -> (int, int):
+    """
+    decode binary unsigned from a leb128 bytes
+    """
+
+    result = 0
+    shift = 0
+    for i, b in enumerate(binary):
+        lower_7_bits = b & 0x7F
+        result |= lower_7_bits << shift
+
+        highest_bit = b & 0x80
+        if not highest_bit:
+            break
+
+        shift += 7
+
+    return i + 1, result
+
+
+def is_aligned(n: int, alignment: int):
+    return (n & (alignment - 1)) == 0
+
+
+def align_up(n: int, alignment: int):
+    return n + (alignment - 1) & ~(alignment - 1)
+
+
+def present_as_vector(content: bytes) -> bytes:
+    v_l = len(content)
+    v_bin = leb128_encode_uint(v_l) if v_l else b"\x00"
+    return v_bin + content
+
+
+def calc_padding(
+    alignment: int, name_bin_len: int, content_len: int, start_pos: int
+) -> bytes:
+    for padding in range(alignment * 2):
+        padding_bin = present_as_vector(b"\x00" * padding)
+        section_length = name_bin_len + len(padding_bin) + content_len
+        section_length_bin = leb128_encode_uint(section_length)
+
+        pos = start_pos + 1 + len(section_length_bin) + name_bin_len + len(padding_bin)
+        if is_aligned(pos, alignment):
+            return padding_bin
+
+
+def build_content(content: bytes, pos: int, adding: bytes) -> (int, bytes):
+    return pos + len(adding), content + adding
+
+
+def create_custom_section_aligned(
+    start_pos: int, name: str, content: bytes, alignment: int = 4
+) -> bytes:
+    """
+        be sure the section_content starts at a X alignment position
+
+          1B
+        | \x00 | length | name vec | padding vec | content |
+        ^                                        ^
+        |                                        |
+    start address                           aligned address
+    """
+
+    name_bin = present_as_vector(name.encode("ascii"))
+    padding_bin = calc_padding(alignment, len(name_bin), len(content), start_pos)
+
+    full_content_bin = b""
+    pos = start_pos
+
+    # custome section id 0
+    pos, full_content_bin = build_content(full_content_bin, pos, b"\x00")
+
+    # custom section length
+    section_length = len(name_bin) + len(padding_bin) + len(content)
+    section_length_bin = leb128_encode_uint(section_length)
+    pos, full_content_bin = build_content(full_content_bin, pos, section_length_bin)
+
+    # custom section name
+    pos, full_content_bin = build_content(full_content_bin, pos, name_bin)
+
+    # padding
+    pos, full_content_bin = build_content(full_content_bin, pos, padding_bin)
+    assert is_aligned(pos, alignment), f"{pos} is not aligned to {alignment}"
+
+    print(f"append .aot @ offset {pos}(0x{pos:X})")
+    _, full_content_bin = build_content(full_content_bin, pos, content)
+
+    return full_content_bin
+
+
+def main(wasm_file: str, aot_file: str, output: str) -> None:
+    cwd = Path.cwd()
+    wasm_file = cwd.joinpath(wasm_file).resolve()
+    aot_file = cwd.joinpath(aot_file).resolve()
+    output = cwd.joinpath(output).resolve()
+
+    assert wasm_file.exists()
+    assert aot_file.exists()
+    output.unlink(missing_ok=True)
+
+    # read aot content
+    with open(aot_file, "rb") as f:
+        aot_content = f.read()
+
+    # append to .wasm
+    with open(wasm_file, "rb") as f_in, open(output, "wb") as f_out:
+        wasm_content = f_in.read(1024)
+        while wasm_content:
+            f_out.write(wasm_content)
+            wasm_content = f_in.read(1024)
+
+        f_out.write(create_custom_section_aligned(f_out.tell(), "aot", aot_content, 4))
+
+    print(f"{wasm_file.name} + {aot_file.name} ==> {output}")
+
+
+if __name__ == "__main__":
+    argparse = argparse.ArgumentParser()
+    argparse.add_argument("--wasm", help="a .wasm")
+    argparse.add_argument("--aot", help="a .aot")
+    argparse.add_argument("-o", "--output", help="the output, still be a .wasm")
+
+    args = argparse.parse_args()
+    main(args.wasm, args.aot, args.output)

+ 210 - 0
test-tools/trans-jitted-func-name/trans_wasm_func_name.py

@@ -0,0 +1,210 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2019 Intel Corporation.  All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+#
+"""
+It is used to translate jitted functions' names(in out.folded) to coorespond name in name section in .wasm
+
+Usage:
+
+After
+```
+$ perf script -i perf.data > out.perf
+
+# fold call stacks
+$ ./FlameGraph/stackcollapse-perf.pl out.perf > out.folded
+```
+
+Add a step:
+```
+# translate jitted functions' names
+$ python translate_wasm_function_name.py --wabt_home <wabt-installation> --folded out.folded <.wasm>
+# out.folded -> out.folded.translated
+$ ls out.folded.translated
+```
+
+Then
+```
+# generate flamegraph
+$ ./FlameGraph/flamegraph.pl out.folded.translated > perf.wasm.svg
+```
+
+"""
+
+import argparse
+import os
+from pathlib import Path
+import re
+import shlex
+import subprocess
+
+
+def preflight_check(wabt_home: Path) -> Path:
+    """
+    if wasm-objdump exists in wabt_home
+    """
+    wasm_objdump_bin = wabt_home.joinpath("bin", "wasm-objdump")
+    if not wasm_objdump_bin.exists():
+        raise RuntimeError(f"wasm-objdump not found in {wabt_home}")
+
+    return wasm_objdump_bin
+
+
+def collect_import_section_content(wasm_objdump_bin: Path, wasm_file: Path) -> dict:
+    """
+    execute "wasm_objdump_bin -j Import -x <wasm_file>" and return a dict like {function: X, global: Y, memory: Z, table: N}
+    """
+    assert wasm_objdump_bin.exists()
+    assert wasm_file.exists()
+
+    command = f"{wasm_objdump_bin} -j Import -x {wasm_file}"
+    p = subprocess.run(
+        shlex.split(command),
+        capture_output=True,
+        check=False,
+        text=True,
+        universal_newlines=True,
+    )
+
+    if p.stderr:
+        return {}
+
+    import_section = {}
+    for line in p.stdout.split(os.linesep):
+        line = line.strip()
+
+        if not line:
+            continue
+
+        if line.startswith(" - func"):
+            import_section.update("function", import_section.get("function", 0) + 1)
+        else:
+            pass
+
+    return import_section
+
+
+def collect_name_section_content(wasm_objdump_bin: Path, wasm_file: Path) -> dict:
+    """
+    execute "wasm_objdump_bin -j name -x wasm_file" and store the output in a list
+    """
+    assert wasm_objdump_bin.exists()
+    assert wasm_file.exists()
+
+    command = f"{wasm_objdump_bin} -j name -x {wasm_file}"
+    p = subprocess.run(
+        shlex.split(command),
+        capture_output=True,
+        check=False,
+        text=True,
+        universal_newlines=True,
+    )
+
+    if p.stderr:
+        raise RuntimeError(f"not found name section in {wasm_file}")
+
+    name_section = {}
+    for line in p.stdout.split(os.linesep):
+        line = line.strip()
+
+        if not line:
+            continue
+
+        # - func[0] <__imported_wasi_snapshot_preview1_fd_close>
+        if line.startswith("- func"):
+            m = re.match(r"- func\[(\d+)\] <(.+)>", line)
+            assert m
+
+            func_index, func_name = m.groups()
+            name_section.update({func_index: func_name})
+
+    assert name_section
+    return name_section
+
+
+def replace_function_name(
+    import_section: dict, name_section: dict, folded_in: str, folded_out: str
+) -> None:
+    """
+    read content in <folded_in>. each line will be like:
+
+    quiche::BalsaFrame::ProcessHeaders;non-virtual thunk to Envoy::Http::Http1::BalsaParser::MessageDone;Envoy::Http::Http1::ConnectionImpl::onMessageComplete;Envoy::Http::Http1::ConnectionImpl::onMessageCompleteImpl;Envoy::Http::Http1::ServerConnectionImpl::onMessageCompleteBase;Envoy::Http::ConnectionManagerImpl::ActiveStream::decodeHeaders;Envoy::Http::FilterManager::decodeHeaders;virtual thunk to Envoy::Extensions::Common::Wasm::Context::decodeHeaders;proxy_wasm::ContextBase::onRequestHeaders;proxy_wasm::wamr::Wamr::getModuleFunctionImpl<proxy_wasm::Word, proxy_wasm::Word, proxy_wasm::Word, proxy_wasm::Word>;wasm_func_call;wasm_runtime_call_wasm;wasm_call_function;call_wasm_with_hw_bound_check;wasm_interp_call_wasm;llvm_jit_call_func_bytecode;wasm_runtime_invoke_native;push_args_end;aot_func_internal#3302;aot_func_internal#3308;asm_sysvec_apic_timer_interrupt;sysvec_apic_timer_interrupt;__sysvec_apic_timer_interrupt;hrtimer_interrupt;__hrtimer_run_queues;__remove_hrtimer;rb_next 1110899
+
+    symbol names are spearated by ";"
+
+    if there is a symbol named like "aot_func#XXX" or "aot_func_internal#XXX", it will be replaced with the function name in name section by index
+    """
+    folded_in = Path(folded_in)
+    assert folded_in.exists()
+    folded_out = Path(folded_out)
+
+    import_function_count = import_section.get("function", 0)
+    with folded_in.open("rt", encoding="utf-8") as f_in, folded_out.open(
+        "wt", encoding="utf-8"
+    ) as f_out:
+        precheck_mode = False
+        for line in f_in:
+            line = line.strip()
+            if "aot_func_internal" in line:
+                precheck_mode = True
+
+        f_in.seek(0)
+        for line in f_in:
+            new_line = []
+            line = line.strip()
+
+            m = re.match(r"(.*) (\d+)", line)
+            syms, samples = m.groups()
+            for sym in syms.split(";"):
+                m = re.match(r"aot_func(_internal)?#(\d+)", sym)
+                if not m:
+                    new_line.append(sym)
+                    continue
+
+                func_idx = m.groups()[-1]
+                if func_idx in name_section:
+                    wasm_func_name = f"[Wasm] {name_section[func_idx]}"
+                else:
+                    wasm_func_name = (
+                        f"[Wasm] function[{func_idx + import_function_count}]"
+                    )
+
+                if precheck_mode:
+                    # aot_func_internal -> xxx
+                    # aot_func --> xxx_precheck
+                    wasm_func_name += "_precheck" if not m.groups()[0] else ""
+                else:
+                    # aot_func --> xxx
+                    pass
+
+                new_line.append(wasm_func_name)
+
+            line = ";".join(new_line)
+            line += f" {samples}"
+            f_out.write(line + os.linesep)
+
+    print(f"⚙️ {folded_in} -> {folded_out}")
+
+
+def main(wabt_home: str, wasm_file: str, folded: str) -> None:
+    wabt_home = Path(wabt_home)
+    wasm_file = Path(wasm_file)
+
+    wasm_objdump_bin = preflight_check(wabt_home)
+    import_section = collect_import_section_content(wasm_objdump_bin, wasm_file)
+    name_section = collect_name_section_content(wasm_objdump_bin, wasm_file)
+
+    replace_function_name(import_section, name_section, folded, folded + ".translated")
+
+
+if __name__ == "__main__":
+    argparse = argparse.ArgumentParser()
+    argparse.add_argument(
+        "--folded", help="stackcollapse-perf.pl generated, like out.folded"
+    )
+    argparse.add_argument("wasm_file", help="wasm file")
+    argparse.add_argument("--wabt_home", help="wabt home, like /opt/wabt-1.0.33")
+
+    args = argparse.parse_args()
+    main(args.wabt_home, args.wasm_file, args.folded)

+ 85 - 16
wamr-compiler/CMakeLists.txt

@@ -45,7 +45,6 @@ add_definitions(-DWASM_ENABLE_AOT_STACK_FRAME=1)
 add_definitions(-DWASM_ENABLE_DUMP_CALL_STACK=1)
 add_definitions(-DWASM_ENABLE_DUMP_CALL_STACK=1)
 add_definitions(-DWASM_ENABLE_PERF_PROFILING=1)
 add_definitions(-DWASM_ENABLE_PERF_PROFILING=1)
 add_definitions(-DWASM_ENABLE_LOAD_CUSTOM_SECTION=1)
 add_definitions(-DWASM_ENABLE_LOAD_CUSTOM_SECTION=1)
-add_definitions(-DWASM_ENABLE_LIB_WASI_THREADS=1)
 add_definitions(-DWASM_ENABLE_MODULE_INST_CONTEXT=1)
 add_definitions(-DWASM_ENABLE_MODULE_INST_CONTEXT=1)
 
 
 add_definitions(-DWASM_ENABLE_GC=1)
 add_definitions(-DWASM_ENABLE_GC=1)
@@ -55,7 +54,11 @@ set (WAMR_STRINGREF_IMPL_SOURCE "STUB")
 
 
 if (WAMR_BUILD_LLVM_LEGACY_PM EQUAL 1)
 if (WAMR_BUILD_LLVM_LEGACY_PM EQUAL 1)
   add_definitions(-DWASM_ENABLE_LLVM_LEGACY_PM=1)
   add_definitions(-DWASM_ENABLE_LLVM_LEGACY_PM=1)
-endif()
+endif ()
+
+if (LINUX)
+  add_definitions(-DWASM_ENABLE_LINUX_PERF=1)
+endif ()
 
 
 if (DEFINED WAMR_BUILD_AOT_FUNC_PREFIX)
 if (DEFINED WAMR_BUILD_AOT_FUNC_PREFIX)
   add_definitions(-DAOT_FUNC_PREFIX="${WAMR_BUILD_AOT_FUNC_PREFIX}")
   add_definitions(-DAOT_FUNC_PREFIX="${WAMR_BUILD_AOT_FUNC_PREFIX}")
@@ -205,32 +208,98 @@ include_directories (${SHARED_DIR}/include
 enable_language (ASM)
 enable_language (ASM)
 
 
 if (NOT MINGW AND NOT MSVC)
 if (NOT MINGW AND NOT MSVC)
-    set(WAMR_BUILD_LIBC_WASI 1)
-else()
-    set(WAMR_BUILD_LIBC_UVWASI 1)
-endif()
+  if ((NOT DEFINED WAMR_BUILD_LIBC_WASI) AND (NOT DEFINED WAMR_BUILD_LIBC_UVWASI))
+    set (WAMR_BUILD_LIBC_WASI 1)
+  endif ()
+
+  if ((WAMR_BUILD_LIBC_WASI EQUAL 1) AND (WAMR_BUILD_LIBC_UVWASI EQUAL 1))
+    message (WARNING "-- pick WAMR_BULID_LIBC_UVWASI when both are enabled")
+    set (WAMR_BUILD_LIBC_WASI 0)
+  endif ()
+else ()
+  if (NOT DEFINED WAMR_BUILD_LIBC_UVWASI)
+    set (WAMR_BUILD_LIBC_UVWASI 1)
+  endif ()
+
+  if (WAMR_BUILD_LIBC_WASI EQUAL 1)
+    message (WARNING "-- don't accept WAMR_BUILD_LIBC_WASI=1 on MINGW or MSVC")
+    set (WAMR_BUILD_LIBC_WASI 0)
+  endif ()
+endif ()
+
+if (NOT DEFINED WAMR_BUILD_LIBC_BUILTIN)
+  set (WAMR_BUILD_LIBC_BUILTIN 1)
+endif ()
+
+if (NOT DEFINED WAMR_BUILD_LIB_PTHREAD)
+  set (WAMR_BUILD_LIB_PTHREAD 1)
+endif ()
+
+if (NOT DEFINED WAMR_BUILD_LIB_WASI_THREADS)
+  set (WAMR_BUILD_LIB_WASI_THREADS 1)
+endif ()
+
+if (WAMR_BUILD_LIBC_UVWASI EQUAL 1)
+  message ("-- Libc WASI enabled with uvwasi implementation")
+endif ()
+
+if (WAMR_BUILD_LIBC_WASI EQUAL 1)
+  message ("-- Libc WASI enabled")
+endif ()
+
+if ((NOT WAMR_BUILD_LIBC_WASI) AND (NOT WAMR_BUILD_LIBC_UVWASI))
+  message ("-- Libc WASI disabled")
+endif ()
+
+if (WAMR_BUILD_LIBC_BUILTIN EQUAL 1)
+  message ("-- Libc builtin enabled")
+else ()
+  message ("-- Libc builtin disabled")
+endif ()
+
+if (WAMR_BUILD_LIB_PTHREAD EQUAL 1)
+  message ("-- Lib pthread enabled")
+else ()
+  message ("-- Lib pthread disabled")
+endif ()
+
+if (WAMR_BUILD_LIB_WASI_THREADS EQUAL 1)
+  message ("-- Lib wasi-threads enabled")
+else ()
+  message ("-- Lib wasi-threads disabled")
+endif ()
 
 
 include (${SHARED_DIR}/platform/${WAMR_BUILD_PLATFORM}/shared_platform.cmake)
 include (${SHARED_DIR}/platform/${WAMR_BUILD_PLATFORM}/shared_platform.cmake)
 include (${SHARED_DIR}/mem-alloc/mem_alloc.cmake)
 include (${SHARED_DIR}/mem-alloc/mem_alloc.cmake)
 include (${SHARED_DIR}/utils/shared_utils.cmake)
 include (${SHARED_DIR}/utils/shared_utils.cmake)
 include (${SHARED_DIR}/utils/uncommon/shared_uncommon.cmake)
 include (${SHARED_DIR}/utils/uncommon/shared_uncommon.cmake)
 include (${IWASM_DIR}/libraries/thread-mgr/thread_mgr.cmake)
 include (${IWASM_DIR}/libraries/thread-mgr/thread_mgr.cmake)
-include (${IWASM_DIR}/libraries/libc-builtin/libc_builtin.cmake)
-if (NOT MINGW)
-  if (NOT MSVC)
-    include (${IWASM_DIR}/libraries/libc-wasi/libc_wasi.cmake)
-  else()
-    include (${IWASM_DIR}/libraries/libc-uvwasi/libc_uvwasi.cmake)
-  endif()
-endif()
-include (${IWASM_DIR}/libraries/lib-pthread/lib_pthread.cmake)
-include (${IWASM_DIR}/libraries/lib-wasi-threads/lib_wasi_threads.cmake)
 include (${IWASM_DIR}/common/iwasm_common.cmake)
 include (${IWASM_DIR}/common/iwasm_common.cmake)
 include (${IWASM_DIR}/common/gc/iwasm_gc.cmake)
 include (${IWASM_DIR}/common/gc/iwasm_gc.cmake)
 include (${IWASM_DIR}/interpreter/iwasm_interp.cmake)
 include (${IWASM_DIR}/interpreter/iwasm_interp.cmake)
 include (${IWASM_DIR}/aot/iwasm_aot.cmake)
 include (${IWASM_DIR}/aot/iwasm_aot.cmake)
 include (${IWASM_DIR}/compilation/iwasm_compl.cmake)
 include (${IWASM_DIR}/compilation/iwasm_compl.cmake)
 
 
+if (WAMR_BUILD_LIBC_BUILTIN EQUAL 1)
+  include (${IWASM_DIR}/libraries/libc-builtin/libc_builtin.cmake)
+endif ()
+
+if (WAMR_BUILD_LIBC_UVWASI EQUAL 1)
+  include (${IWASM_DIR}/libraries/libc-uvwasi/libc_uvwasi.cmake)
+endif ()
+
+if (WAMR_BUILD_LIBC_WASI EQUAL 1)
+  include (${IWASM_DIR}/libraries/libc-wasi/libc_wasi.cmake)
+endif ()
+
+if (WAMR_BUILD_LIB_PTHREAD EQUAL 1)
+  include (${IWASM_DIR}/libraries/lib-pthread/lib_pthread.cmake)
+endif ()
+
+if (WAMR_BUILD_LIB_WASI_THREADS EQUAL 1)
+  include (${IWASM_DIR}/libraries/lib-wasi-threads/lib_wasi_threads.cmake)
+endif ()
+
 # set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wconversion -Wsign-conversion")
 # set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wconversion -Wsign-conversion")
 if (WAMR_BUILD_TARGET MATCHES "X86_.*" OR WAMR_BUILD_TARGET STREQUAL "AMD_64")
 if (WAMR_BUILD_TARGET MATCHES "X86_.*" OR WAMR_BUILD_TARGET STREQUAL "AMD_64")
   if (NOT (CMAKE_C_COMPILER MATCHES ".*clang.*" OR CMAKE_C_COMPILER_ID MATCHES ".*Clang" OR MSVC))
   if (NOT (CMAKE_C_COMPILER MATCHES ".*clang.*" OR CMAKE_C_COMPILER_ID MATCHES ".*Clang" OR MSVC))

+ 17 - 3
wamr-compiler/main.c

@@ -186,9 +186,12 @@ print_help()
     printf("                            multiple names, e.g.\n");
     printf("                            multiple names, e.g.\n");
     printf("                                --emit-custom-sections=section1,section2,sectionN\n");
     printf("                                --emit-custom-sections=section1,section2,sectionN\n");
 #if BH_HAS_DLFCN
 #if BH_HAS_DLFCN
-    printf("  --native-lib=<lib>       Register native libraries to the WASM module, which\n");
-    printf("                           are shared object (.so) files, for example:\n");
-    printf("                             --native-lib=test1.so --native-lib=test2.so\n");
+    printf("  --native-lib=<lib>        Register native libraries to the WASM module, which\n");
+    printf("                            are shared object (.so) files, for example:\n");
+    printf("                              --native-lib=test1.so --native-lib=test2.so\n");
+#endif
+#if WASM_ENABLE_LINUX_PERF != 0
+    printf("  --enable-linux-perf       Enable linux perf support\n");
 #endif
 #endif
     printf("  -v=n                      Set log verbose level (0 to 5, default is 2), larger with more log\n");
     printf("  -v=n                      Set log verbose level (0 to 5, default is 2), larger with more log\n");
     printf("  --version                 Show version information\n");
     printf("  --version                 Show version information\n");
@@ -327,6 +330,9 @@ main(int argc, char *argv[])
     void *native_handle_list[8] = { NULL };
     void *native_handle_list[8] = { NULL };
     uint32 native_handle_count = 0;
     uint32 native_handle_count = 0;
 #endif
 #endif
+#if WASM_ENABLE_LINUX_PERF != 0
+    bool enable_linux_perf = false;
+#endif
 
 
     option.opt_level = 3;
     option.opt_level = 3;
     option.size_level = 3;
     option.size_level = 3;
@@ -533,6 +539,11 @@ main(int argc, char *argv[])
             }
             }
             native_lib_list[native_lib_count++] = argv[0] + 13;
             native_lib_list[native_lib_count++] = argv[0] + 13;
         }
         }
+#endif
+#if WASM_ENABLE_LINUX_PERF != 0
+        else if (!strncmp(argv[0], "--enable-linux-perf", 19)) {
+            enable_linux_perf = true;
+        }
 #endif
 #endif
         else if (!strncmp(argv[0], "--version", 9)) {
         else if (!strncmp(argv[0], "--version", 9)) {
             uint32 major, minor, patch;
             uint32 major, minor, patch;
@@ -591,6 +602,9 @@ main(int argc, char *argv[])
     init_args.mem_alloc_option.allocator.malloc_func = malloc;
     init_args.mem_alloc_option.allocator.malloc_func = malloc;
     init_args.mem_alloc_option.allocator.realloc_func = realloc;
     init_args.mem_alloc_option.allocator.realloc_func = realloc;
     init_args.mem_alloc_option.allocator.free_func = free;
     init_args.mem_alloc_option.allocator.free_func = free;
+#if WASM_ENABLE_LINUX_PERF != 0
+    init_args.enable_linux_perf = enable_linux_perf;
+#endif
 
 
     /* initialize runtime environment */
     /* initialize runtime environment */
     if (!wasm_runtime_full_init(&init_args)) {
     if (!wasm_runtime_full_init(&init_args)) {