Quellcode durchsuchen

Refine the wasm-c-api native func call process of aot mode (#640)

Wenyong Huang vor 4 Jahren
Ursprung
Commit
ba922b0d0d

+ 192 - 20
core/iwasm/aot/aot_runtime.c

@@ -13,6 +13,7 @@
 #if WASM_ENABLE_THREAD_MGR != 0
 #include "../libraries/thread-mgr/thread_manager.h"
 #endif
+#include "../common/wasm_c_api_internal.h"
 
 static void
 set_error_buf(char *error_buf, uint32 error_buf_size, const char *string)
@@ -1097,6 +1098,18 @@ fail:
     return NULL;
 }
 
+bool
+aot_create_exec_env_singleton(AOTModuleInstance *module_inst)
+{
+    WASMExecEnv *exec_env =
+        wasm_exec_env_create((WASMModuleInstanceCommon *)module_inst,
+                             module_inst->default_wasm_stack_size);
+    if (exec_env)
+        module_inst->exec_env_singleton.ptr = exec_env;
+
+    return exec_env ? true : false;
+}
+
 void
 aot_deinstantiate(AOTModuleInstance *module_inst, bool is_sub_inst)
 {
@@ -1127,6 +1140,10 @@ aot_deinstantiate(AOTModuleInstance *module_inst, bool is_sub_inst)
     if (module_inst->func_type_indexes.ptr)
         wasm_runtime_free(module_inst->func_type_indexes.ptr);
 
+    if (module_inst->exec_env_singleton.ptr)
+        wasm_exec_env_destroy((WASMExecEnv *)
+                              module_inst->exec_env_singleton.ptr);
+
     wasm_runtime_free(module_inst);
 }
 
@@ -1287,6 +1304,9 @@ invoke_native_with_hw_bound_check(WASMExecEnv *exec_env, void *func_ptr,
     WASMJmpBuf jmpbuf_node = { 0 }, *jmpbuf_node_pop;
     uint32 page_size = os_getpagesize();
     uint32 guard_page_count = STACK_OVERFLOW_CHECK_GUARD_PAGE_COUNT;
+    uint16 param_count = func_type->param_count;
+    uint16 result_count = func_type->result_count;
+    const uint8 *types = func_type->types;
 #if BH_PLATFORM_WINDOWS
     const char *exce;
     int result;
@@ -1316,9 +1336,31 @@ invoke_native_with_hw_bound_check(WASMExecEnv *exec_env, void *func_ptr,
 
     aot_exec_env = exec_env;
     if (os_setjmp(jmpbuf_node.jmpbuf) == 0) {
-        ret = wasm_runtime_invoke_native(exec_env, func_ptr, func_type,
-                                         signature, attachment,
-                                         argv, argc, argv_ret);
+        /* Quick call with func_ptr if the function signature is simple */
+        if (!signature && param_count == 1 && types[0] == VALUE_TYPE_I32) {
+            if (result_count == 0) {
+                void (*NativeFunc)(WASMExecEnv*, uint32) =
+                    (void (*)(WASMExecEnv*, uint32))func_ptr;
+                NativeFunc(exec_env, argv[0]);
+                ret = aot_get_exception(module_inst) ? false : true;
+            }
+            else if (result_count == 1 && types[param_count] == VALUE_TYPE_I32) {
+                uint32 (*NativeFunc)(WASMExecEnv*, uint32) =
+                    (uint32 (*)(WASMExecEnv*, uint32))func_ptr;
+                argv_ret[0] = NativeFunc(exec_env, argv[0]);
+                ret = aot_get_exception(module_inst) ? false : true;
+            }
+            else {
+                ret = wasm_runtime_invoke_native(exec_env, func_ptr, func_type,
+                                                 signature, attachment,
+                                                 argv, argc, argv_ret);
+            }
+        }
+        else {
+            ret = wasm_runtime_invoke_native(exec_env, func_ptr, func_type,
+                                             signature, attachment,
+                                             argv, argc, argv_ret);
+        }
 #ifdef BH_PLATFORM_WINDOWS
         if ((exce = aot_get_exception(module_inst))
             && strstr(exce, "native stack overflow")) {
@@ -1339,8 +1381,10 @@ invoke_native_with_hw_bound_check(WASMExecEnv *exec_env, void *func_ptr,
     if (!exec_env->jmpbuf_stack_top) {
         *p_aot_exec_env = NULL;
     }
-    os_sigreturn();
-    os_signal_unmask();
+    if (!ret) {
+        os_sigreturn();
+        os_signal_unmask();
+    }
     (void)jmpbuf_node_pop;
     return ret;
 }
@@ -2157,6 +2201,140 @@ aot_is_wasm_type_equal(AOTModuleInstance *module_inst,
     return wasm_type_equal(type1, type2);
 }
 
+static inline bool
+argv_to_params(wasm_val_t *out_params, const uint32 *argv,
+               AOTFuncType *func_type)
+{
+    wasm_val_t *param = out_params;
+    uint32 i = 0, *u32;
+
+    for (i = 0; i < func_type->param_count; i++, param++) {
+        switch (func_type->types[i]) {
+            case VALUE_TYPE_I32:
+                param->kind = WASM_I32;
+                param->of.i32 = *argv++;
+                break;
+            case VALUE_TYPE_I64:
+                param->kind = WASM_I64;
+                u32 = (uint32*)&param->of.i64;
+                u32[0] = *argv++;
+                u32[1] = *argv++;
+                break;
+            case VALUE_TYPE_F32:
+                param->kind = WASM_F32;
+                param->of.f32 = *(float32 *)argv++;
+                break;
+            case VALUE_TYPE_F64:
+                param->kind = WASM_F64;
+                u32 = (uint32*)&param->of.i64;
+                u32[0] = *argv++;
+                u32[1] = *argv++;
+                break;
+            default:
+                return false;
+        }
+    }
+
+    return true;
+}
+
+static inline bool
+results_to_argv(uint32 *out_argv, const wasm_val_t *results,
+                AOTFuncType *func_type)
+{
+    const wasm_val_t *result = results;
+    uint32 *argv = out_argv, *u32, i;
+    uint8 *result_types = func_type->types + func_type->param_count;
+
+    for (i = 0; i < func_type->result_count; i++, result++) {
+        switch (result_types[i]) {
+            case VALUE_TYPE_I32:
+            case VALUE_TYPE_F32:
+                *(int32*)argv++ = result->of.i32;
+                break;
+            case VALUE_TYPE_I64:
+            case VALUE_TYPE_F64:
+                u32 = (uint32*)&result->of.i64;
+                *argv++ = u32[0];
+                *argv++ = u32[1];
+                break;
+            default:
+                return false;
+        }
+    }
+
+    return true;
+}
+
+static inline bool
+invoke_wasm_c_api_native(AOTModuleInstance *module_inst, void *func_ptr,
+                         AOTFuncType *func_type, uint32 argc, uint32 *argv,
+                         bool with_env, void *wasm_c_api_env)
+{
+    wasm_val_t params_buf[16], results_buf[4];
+    wasm_val_t *params = params_buf, *results = results_buf;
+    wasm_trap_t *trap = NULL;
+    bool ret = false;
+    char fmt[16];
+
+    if (func_type->param_count > 16
+        && !(params = wasm_runtime_malloc(sizeof(wasm_val_t)
+                                          * func_type->param_count))) {
+        aot_set_exception_with_id(module_inst, EXCE_OUT_OF_MEMORY);
+        return false;
+    }
+
+    if (!argv_to_params(params, argv, func_type)) {
+        aot_set_exception(module_inst, "unsupported param type");
+        goto fail;
+    }
+
+    if (!with_env) {
+        wasm_func_callback_t callback = (wasm_func_callback_t)func_ptr;
+        trap = callback(params, results);
+    }
+    else {
+        wasm_func_callback_with_env_t callback =
+                            (wasm_func_callback_with_env_t)func_ptr;
+        trap = callback(wasm_c_api_env, params, results);
+    }
+    if (trap) {
+        if (trap->message->data) {
+            snprintf(fmt, sizeof(fmt), "%%%us", (uint32)trap->message->size);
+            snprintf(module_inst->cur_exception,
+                     sizeof(module_inst->cur_exception),
+                     fmt, trap->message->data);
+        }
+        else {
+            aot_set_exception(module_inst,
+                              "native function throw unknown exception");
+        }
+        wasm_trap_delete(trap);
+        goto fail;
+    }
+
+    if (func_type->result_count > 4
+        && !(results = wasm_runtime_malloc(sizeof(wasm_val_t)
+                                           * func_type->result_count))) {
+        aot_set_exception_with_id(module_inst, EXCE_OUT_OF_MEMORY);
+        goto fail;
+    }
+
+    if (!results_to_argv(argv, results, func_type)) {
+        aot_set_exception(module_inst, "unsupported result type");
+        goto fail;
+    }
+
+    ret = true;
+
+fail:
+    if (params != params_buf)
+        wasm_runtime_free(params);
+    if (results != results_buf)
+        wasm_runtime_free(results);
+    return ret;
+}
+
 bool
 aot_invoke_native(WASMExecEnv *exec_env, uint32 func_idx,
                   uint32 argc, uint32 *argv)
@@ -2174,19 +2352,6 @@ aot_invoke_native(WASMExecEnv *exec_env, uint32 func_idx,
     void *attachment;
     char buf[128];
 
-#ifdef OS_ENABLE_HW_BOUND_CHECK
-    uint32 page_size = os_getpagesize();
-    uint32 guard_page_count = STACK_OVERFLOW_CHECK_GUARD_PAGE_COUNT;
-    /* Check native stack overflow firstly to ensure we have enough
-       native stack to run the following codes before actually calling
-       the aot function in invokeNative function. */
-    if ((uint8*)&module_inst < exec_env->native_stack_boundary
-                               + page_size * (guard_page_count + 1)) {
-        aot_set_exception_with_id(module_inst, EXCE_NATIVE_STACK_OVERFLOW);
-        return false;
-    }
-#endif
-
     bh_assert(func_idx < aot_module->import_func_count);
 
     import_func = aot_module->import_funcs + func_idx;
@@ -2198,14 +2363,21 @@ aot_invoke_native(WASMExecEnv *exec_env, uint32 func_idx,
         return false;
     }
 
-    signature = import_func->signature;
     attachment = import_func->attachment;
-    if (!import_func->call_conv_raw) {
+    if (import_func->call_conv_wasm_c_api) {
+        return invoke_wasm_c_api_native(module_inst, func_ptr,
+                                       func_type, argc, argv,
+                                       import_func->wasm_c_api_with_env,
+                                       attachment);
+    }
+    else if (!import_func->call_conv_raw) {
+        signature = import_func->signature;
         return wasm_runtime_invoke_native(exec_env, func_ptr,
                                           func_type, signature, attachment,
                                           argv, argc, argv);
     }
     else {
+        signature = import_func->signature;
         return wasm_runtime_invoke_native_raw(exec_env, func_ptr,
                                               func_type, signature, attachment,
                                               argv, argc, argv);

+ 7 - 1
core/iwasm/aot/aot_runtime.h

@@ -346,13 +346,15 @@ typedef struct AOTModuleInstance {
     /* function performance profiling info list */
     AOTPointer func_perf_profilings;
 
+    AOTPointer exec_env_singleton;
+
     /* others */
     uint32 temp_ret;
     uint32 llvm_stack;
     uint32 default_wasm_stack_size;
 
     /* reserved */
-    uint32 reserved[11];
+    uint32 reserved[9];
 
    /*
     * +------------------------------+ <-- memories.ptr
@@ -522,6 +524,10 @@ bool
 aot_create_exec_env_and_call_function(AOTModuleInstance *module_inst,
                                       AOTFunctionInstance *function,
                                       unsigned argc, uint32 argv[]);
+
+bool
+aot_create_exec_env_singleton(AOTModuleInstance *module_inst);
+
 /**
  * Set AOT module instance exception with exception string
  *

+ 42 - 26
core/iwasm/common/wasm_c_api.c

@@ -2335,14 +2335,12 @@ wasm_func_call(const wasm_func_t *func,
     /* a int64 or float64 parameter means 2 */
     uint32 argc = 0;
     /* a parameter list and a return value list */
-    uint32 *argv = NULL;
+    uint32 argv_buf[32], *argv = argv_buf;
     WASMFunctionInstanceCommon *func_comm_rt = NULL;
+    WASMExecEnv *exec_env = NULL;
     size_t param_count, result_count, alloc_count;
 
-    if (!func || !func->type || !func->inst_comm_rt
-        || !valid_module_type(func->inst_comm_rt->module_type)) {
-        return NULL;
-    }
+    bh_assert(func && func->type && func->inst_comm_rt);
 
     cur_trap = NULL;
 
@@ -2355,20 +2353,23 @@ wasm_func_call(const wasm_func_t *func,
 
 #if WASM_ENABLE_AOT != 0
     if (func->inst_comm_rt->module_type == Wasm_Module_AoT) {
-        AOTModuleInstance *inst_aot = (AOTModuleInstance *)func->inst_comm_rt;
-        AOTModule *module_aot = (AOTModule *)inst_aot->aot_module.ptr;
-
-        uint32 export_i = 0, export_func_j = 0;
-        for (; export_i < module_aot->export_count; ++export_i) {
-            AOTExport *export = module_aot->exports + export_i;
-            if (export->kind == EXPORT_KIND_FUNC) {
-                if (export->index == func->func_idx_rt) {
-                    func_comm_rt =
-                      (AOTFunctionInstance *)inst_aot->export_funcs.ptr
-                      + export_func_j;
-                    break;
+        if (!(func_comm_rt = func->func_comm_rt)) {
+            AOTModuleInstance *inst_aot = (AOTModuleInstance *)func->inst_comm_rt;
+            AOTModule *module_aot = (AOTModule *)inst_aot->aot_module.ptr;
+            uint32 export_i = 0, export_func_j = 0;
+
+            for (; export_i < module_aot->export_count; ++export_i) {
+                AOTExport *export = module_aot->exports + export_i;
+                if (export->kind == EXPORT_KIND_FUNC) {
+                    if (export->index == func->func_idx_rt) {
+                        func_comm_rt =
+                            (AOTFunctionInstance *)inst_aot->export_funcs.ptr
+                            + export_func_j;
+                        ((wasm_func_t*)func)->func_comm_rt = func_comm_rt;
+                        break;
+                    }
+                    export_func_j++;
                 }
-                export_func_j++;
             }
         }
     }
@@ -2381,7 +2382,7 @@ wasm_func_call(const wasm_func_t *func,
     param_count = wasm_func_param_arity(func);
     result_count = wasm_func_result_arity(func);
     alloc_count = (param_count > result_count) ? param_count : result_count;
-    if (alloc_count) {
+    if (alloc_count > sizeof(argv_buf)/sizeof(uint64)) {
         if (!(argv = malloc_internal(sizeof(uint64) * alloc_count))) {
             goto failed;
         }
@@ -2394,8 +2395,12 @@ wasm_func_call(const wasm_func_t *func,
         goto failed;
     }
 
-    if (!wasm_runtime_create_exec_env_and_call_wasm(
-          func->inst_comm_rt, func_comm_rt, argc, argv)) {
+    exec_env = wasm_runtime_get_exec_env_singleton(func->inst_comm_rt);
+    if (!exec_env) {
+        goto failed;
+    }
+
+    if (!wasm_runtime_call_wasm(exec_env, func_comm_rt, argc, argv)) {
         if (wasm_runtime_get_exception(func->inst_comm_rt)) {
             LOG_DEBUG(wasm_runtime_get_exception(func->inst_comm_rt));
             goto failed;
@@ -2410,11 +2415,13 @@ wasm_func_call(const wasm_func_t *func,
         }
     }
 
-    FREEIF(argv);
+    if (argv != argv_buf)
+        wasm_runtime_free(argv);
     return NULL;
 
 failed:
-    FREEIF(argv);
+    if (argv != argv_buf)
+        wasm_runtime_free(argv);
     if (cur_trap) {
         return cur_trap;
     }
@@ -3392,9 +3399,14 @@ aot_link_func(const wasm_instance_t *inst,
         return false;
     }
 
-    import_aot_func->call_conv_raw = true;
-    import_aot_func->attachment = cloned;
-    import_aot_func->func_ptr_linked = native_func_trampoline;
+    import_aot_func->call_conv_wasm_c_api = true;
+    import_aot_func->wasm_c_api_with_env = import->with_env;
+    if (import->with_env) {
+        import_aot_func->func_ptr_linked = import->u.cb_env.cb;
+        import_aot_func->attachment = import->u.cb_env.env;
+    }
+    else
+        import_aot_func->func_ptr_linked = import->u.cb;
     import->func_idx_rt = import_func_idx_rt;
 
     return true;
@@ -3668,6 +3680,10 @@ wasm_instance_new(wasm_store_t *store,
         goto failed;
     }
 
+    if (!wasm_runtime_create_exec_env_singleton(instance->inst_comm_rt)) {
+        goto failed;
+    }
+
     /* fill with inst */
     for (i = 0; imports && i < (uint32)import_count; ++i) {
         wasm_extern_t *import = (wasm_extern_t *)imports[i];

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

@@ -112,6 +112,7 @@ struct wasm_func_t {
      */
     uint16 func_idx_rt;
     WASMModuleInstanceCommon *inst_comm_rt;
+    WASMFunctionInstanceCommon *func_comm_rt;
 };
 
 struct wasm_global_t {

+ 29 - 0
core/iwasm/common/wasm_runtime_common.c

@@ -1397,6 +1397,35 @@ wasm_runtime_create_exec_env_and_call_wasm(WASMModuleInstanceCommon *module_inst
     return ret;
 }
 
+bool
+wasm_runtime_create_exec_env_singleton(WASMModuleInstanceCommon *module_inst)
+{
+#if WASM_ENABLE_INTERP != 0
+    if (module_inst->module_type == Wasm_Module_Bytecode)
+        return wasm_create_exec_env_singleton((WASMModuleInstance *)module_inst);
+#endif
+#if WASM_ENABLE_AOT != 0
+    if (module_inst->module_type == Wasm_Module_AoT)
+        return aot_create_exec_env_singleton((AOTModuleInstance *)module_inst);
+#endif
+    return false;
+}
+
+WASMExecEnv *
+wasm_runtime_get_exec_env_singleton(WASMModuleInstanceCommon *module_inst)
+{
+#if WASM_ENABLE_INTERP != 0
+    if (module_inst->module_type == Wasm_Module_Bytecode)
+        return ((WASMModuleInstance *)module_inst)->exec_env_singleton;
+#endif
+#if WASM_ENABLE_AOT != 0
+    if (module_inst->module_type == Wasm_Module_AoT)
+        return (WASMExecEnv *)
+               ((AOTModuleInstance *)module_inst)->exec_env_singleton.ptr;
+#endif
+    return NULL;
+}
+
 void
 wasm_runtime_set_exception(WASMModuleInstanceCommon *module_inst,
                            const char *exception)

+ 6 - 0
core/iwasm/common/wasm_runtime_common.h

@@ -467,6 +467,12 @@ wasm_runtime_create_exec_env_and_call_wasm(WASMModuleInstanceCommon *module_inst
                                            WASMFunctionInstanceCommon *function,
                                            uint32 argc, uint32 argv[]);
 
+bool
+wasm_runtime_create_exec_env_singleton(WASMModuleInstanceCommon *module_inst);
+
+WASMExecEnv *
+wasm_runtime_get_exec_env_singleton(WASMModuleInstanceCommon *module_inst);
+
 /* See wasm_export.h for description */
 WASM_RUNTIME_API_EXTERN bool
 wasm_application_execute_main(WASMModuleInstanceCommon *module_inst,

+ 1 - 0
core/iwasm/compilation/aot.c

@@ -290,6 +290,7 @@ aot_create_import_funcs(const WASMModule *module)
     import_funcs[i].signature = import_func->signature;
     import_funcs[i].attachment = import_func->attachment;
     import_funcs[i].call_conv_raw = import_func->call_conv_raw;
+    import_funcs[i].call_conv_wasm_c_api = false;
     /* Resolve function type index */
     for (j = 0; j < module->type_count; j++)
       if (import_func->func_type == module->types[j]) {

+ 2 - 0
core/iwasm/compilation/aot.h

@@ -148,6 +148,8 @@ typedef struct AOTImportFunc {
   /* attachment */
   void *attachment;
   bool call_conv_raw;
+  bool call_conv_wasm_c_api;
+  bool wasm_c_api_with_env;
 } AOTImportFunc;
 
 /**

+ 100 - 0
core/iwasm/compilation/aot_compiler.c

@@ -2130,3 +2130,103 @@ aot_emit_object_file(AOTCompContext *comp_ctx, char *file_name)
     return true;
 }
 
+#if WASM_ENABLE_REF_TYPES != 0
+extern void
+wasm_set_ref_types_flag(bool enable);
+#endif
+
+uint8*
+aot_compile_wasm_file(const uint8 *wasm_file_buf, uint32 wasm_file_size,
+                      uint32 opt_level, uint32 size_level,
+                      uint32 *p_aot_file_size)
+{
+    WASMModuleCommon *wasm_module = NULL;
+    AOTCompData *comp_data = NULL;
+    AOTCompContext *comp_ctx = NULL;
+    RuntimeInitArgs init_args;
+    AOTCompOption option = { 0 };
+    uint8 *aot_file_buf = NULL;
+    uint32 aot_file_size;
+    char error_buf[128];
+
+    option.is_jit_mode = false;
+    option.opt_level = opt_level;
+    option.size_level = size_level;
+    option.output_format = AOT_FORMAT_FILE;
+    /* default value, enable or disable depends on the platform */
+    option.bounds_checks = 2;
+    option.enable_simd = true;
+    option.enable_aux_stack_check = true;
+#if WASM_ENABLE_BULK_MEMORY != 0
+    option.enable_bulk_memory = true;
+#endif
+#if WASM_ENABLE_THREAD_MGR != 0
+    option.enable_thread_mgr = true;
+#endif
+#if WASM_ENABLE_TAIL_CALL != 0
+  option.enable_tail_call = true;
+#endif
+#if WASM_ENABLE_SIMD != 0
+  option.enable_simd = true;
+#endif
+#if WASM_ENABLE_REF_TYPES != 0
+    option.enable_ref_types = true;
+#endif
+#if (WASM_ENABLE_PERF_PROFILING != 0) || (WASM_ENABLE_DUMP_CALL_STACK != 0)
+    option.enable_aux_stack_frame = true;
+#endif
+
+#if WASM_ENABLE_REF_TYPES != 0
+    wasm_set_ref_types_flag(option.enable_ref_types);
+#endif
+
+    memset(&init_args, 0, sizeof(RuntimeInitArgs));
+
+    init_args.mem_alloc_type = Alloc_With_Allocator;
+    init_args.mem_alloc_option.allocator.malloc_func = malloc;
+    init_args.mem_alloc_option.allocator.realloc_func = realloc;
+    init_args.mem_alloc_option.allocator.free_func = free;
+
+    /* load WASM module */
+    if (!(wasm_module = (WASMModuleCommon*)
+                        wasm_load(wasm_file_buf, wasm_file_size,
+                                  error_buf, sizeof(error_buf)))) {
+        os_printf("%s\n", error_buf);
+        aot_set_last_error(error_buf);
+        return NULL;
+    }
+
+    if (!(comp_data = aot_create_comp_data((WASMModule*)wasm_module))) {
+        os_printf("%s\n", aot_get_last_error());
+        goto fail1;
+    }
+
+    if (!(comp_ctx = aot_create_comp_context(comp_data, &option))) {
+        os_printf("%s\n", aot_get_last_error());
+        goto fail2;
+    }
+
+    if (!aot_compile_wasm(comp_ctx)) {
+        os_printf("%s\n", aot_get_last_error());
+        goto fail3;
+    }
+
+    if (!(aot_file_buf = aot_emit_aot_file_buf(comp_ctx, comp_data,
+                                               &aot_file_size))) {
+        os_printf("%s\n", aot_get_last_error());
+        goto fail3;
+    }
+
+    *p_aot_file_size = aot_file_size;
+
+fail3:
+    /* Destroy compiler context */
+    aot_destroy_comp_context(comp_ctx);
+fail2:
+  /* Destroy compile data */
+    aot_destroy_comp_data(comp_data);
+fail1:
+    wasm_runtime_unload(wasm_module);
+
+    return aot_file_buf;
+}

+ 10 - 0
core/iwasm/compilation/aot_compiler.h

@@ -368,9 +368,19 @@ aot_emit_aot_file(AOTCompContext *comp_ctx,
                   AOTCompData *comp_data,
                   const char *file_name);
 
+uint8_t*
+aot_emit_aot_file_buf(AOTCompContext *comp_ctx,
+                      AOTCompData *comp_data,
+                      uint32_t *p_aot_file_size);
+
 bool
 aot_emit_object_file(AOTCompContext *comp_ctx, char *file_name);
 
+uint8_t*
+aot_compile_wasm_file(const uint8_t *wasm_file_buf, uint32_t wasm_file_size,
+                      uint32_t opt_level, uint32_t size_level,
+                      uint32_t *p_aot_file_size);
+
 #ifdef __cplusplus
 } /* end of extern "C" */
 #endif

+ 38 - 14
core/iwasm/compilation/aot_emit_aot_file.c

@@ -2208,20 +2208,17 @@ fail:
     return NULL;
 }
 
-bool
-aot_emit_aot_file(AOTCompContext *comp_ctx, AOTCompData *comp_data,
-                  const char *file_name)
+uint8*
+aot_emit_aot_file_buf(AOTCompContext *comp_ctx,
+                      AOTCompData *comp_data,
+                      uint32 *p_aot_file_size)
 {
     AOTObjectData *obj_data = aot_obj_data_create(comp_ctx);
     uint8 *aot_file_buf, *buf, *buf_end;
     uint32 aot_file_size, offset = 0;
-    bool ret = false;
-    FILE *file;
 
     if (!obj_data)
-        return false;
-
-    bh_print_time("Begin to emit AOT file");
+        return NULL;
 
     aot_file_size = get_aot_file_size(comp_ctx, comp_data, obj_data);
 
@@ -2251,25 +2248,52 @@ aot_emit_aot_file(AOTCompContext *comp_ctx, AOTCompData *comp_data,
         goto fail2;
     }
 
+    *p_aot_file_size = aot_file_size;
+
+    aot_obj_data_destroy(obj_data);
+    return aot_file_buf;
+
+fail2:
+    wasm_runtime_free(aot_file_buf);
+
+fail1:
+    aot_obj_data_destroy(obj_data);
+    return NULL;
+}
+
+bool
+aot_emit_aot_file(AOTCompContext *comp_ctx, AOTCompData *comp_data,
+                  const char *file_name)
+{
+    uint8 *aot_file_buf;
+    uint32 aot_file_size;
+    bool ret = false;
+    FILE *file;
+
+    bh_print_time("Begin to emit AOT file");
+
+    if (!(aot_file_buf = aot_emit_aot_file_buf(comp_ctx, comp_data,
+                                               &aot_file_size))) {
+        return false;
+    }
+
     /* write buffer to file */
     if (!(file = fopen(file_name, "wb"))) {
         aot_set_last_error("open or create aot file failed.");
-        goto fail2;
+        goto fail1;
     }
     if (!fwrite(aot_file_buf, aot_file_size, 1, file)) {
         aot_set_last_error("write to aot file failed.");
-        goto fail3;
+        goto fail2;
     }
 
     ret = true;
 
-fail3:
+fail2:
     fclose(file);
 
-fail2:
+fail1:
     wasm_runtime_free(aot_file_buf);
 
-fail1:
-    aot_obj_data_destroy(obj_data);
     return ret;
 }

+ 5 - 0
core/iwasm/include/aot_export.h

@@ -77,6 +77,11 @@ aot_emit_aot_file(aot_comp_context_t comp_ctx,
 void
 aot_destroy_aot_file(uint8_t *aot_file);
 
+uint8_t*
+aot_compile_wasm_file(const uint8_t *wasm_file_buf, uint32_t wasm_file_size,
+                      uint32_t opt_level, uint32_t size_level,
+                      uint32_t *p_aot_file_size);
+
 char*
 aot_get_last_error();
 

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

@@ -1574,6 +1574,9 @@ wasm_deinstantiate(WASMModuleInstance *module_inst, bool is_sub_inst)
     wasm_externref_cleanup((WASMModuleInstanceCommon*)module_inst);
 #endif
 
+    if (module_inst->exec_env_singleton)
+        wasm_exec_env_destroy(module_inst->exec_env_singleton);
+
     wasm_runtime_free(module_inst);
 }
 
@@ -1701,6 +1704,18 @@ wasm_create_exec_env_and_call_function(WASMModuleInstance *module_inst,
     return ret;
 }
 
+bool
+wasm_create_exec_env_singleton(WASMModuleInstance *module_inst)
+{
+    WASMExecEnv *exec_env =
+        wasm_exec_env_create((WASMModuleInstanceCommon *)module_inst,
+                             module_inst->default_wasm_stack_size);
+    if (exec_env)
+        module_inst->exec_env_singleton = exec_env;
+
+    return exec_env ? true : false;
+}
+
 void
 wasm_set_exception(WASMModuleInstance *module_inst,
                    const char *exception)

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

@@ -198,6 +198,8 @@ struct WASMModuleInstance {
     WASIContext *wasi_ctx;
 #endif
 
+    WASMExecEnv *exec_env_singleton;
+
     uint32 temp_ret;
     uint32 llvm_stack;
 
@@ -318,6 +320,9 @@ wasm_create_exec_env_and_call_function(WASMModuleInstance *module_inst,
                                        WASMFunctionInstance *function,
                                        unsigned argc, uint32 argv[]);
 
+bool
+wasm_create_exec_env_singleton(WASMModuleInstance *module_inst);
+
 void
 wasm_set_exception(WASMModuleInstance *module, const char *exception);