@@ -814,6 +814,15 @@ aot_instantiate(AOTModule *module, bool is_sub_inst,
814814#endif
815815 module_inst -> default_wasm_stack_size = stack_size ;
816816
817+ #if WASM_ENABLE_PERF_PROFILING != 0
818+ total_size = (uint64 )sizeof (AOTFuncPerfProfInfo ) *
819+ (module -> import_func_count + module -> func_count );
820+ if (!(module_inst -> func_perf_profilings .ptr =
821+ runtime_malloc (total_size , error_buf , error_buf_size ))) {
822+ goto fail ;
823+ }
824+ #endif
825+
817826 /* Execute __post_instantiate function and start function*/
818827 if (!execute_post_inst_function (module_inst )
819828 || !execute_start_function (module_inst )) {
@@ -866,6 +875,11 @@ aot_deinstantiate(AOTModuleInstance *module_inst, bool is_sub_inst)
866875 wasm_runtime_destroy_wasi ((WASMModuleInstanceCommon * )module_inst );
867876#endif
868877
878+ #if WASM_ENABLE_PERF_PROFILING != 0
879+ if (module_inst -> func_perf_profilings .ptr )
880+ wasm_runtime_free (module_inst -> func_perf_profilings .ptr );
881+ #endif
882+
869883 if (module_inst -> memories .ptr )
870884 memories_deinstantiate (module_inst );
871885
@@ -1128,16 +1142,38 @@ aot_call_function(WASMExecEnv *exec_env,
11281142 cell_num += wasm_value_type_cell_num (ext_ret_types [i ]);
11291143 }
11301144
1145+ #if (WASM_ENABLE_DUMP_CALL_STACK != 0 ) || (WASM_ENABLE_PERF_PROFILING != 0 )
1146+ if (!aot_alloc_frame (exec_env , function -> func_index )) {
1147+ wasm_runtime_free (argv1 );
1148+ return false;
1149+ }
1150+ #endif
1151+
11311152 ret = invoke_native_internal (exec_env , function -> u .func .func_ptr ,
11321153 func_type , NULL , NULL , argv1 , argc , argv );
1154+
11331155 if (!ret || aot_get_exception (module_inst )) {
11341156 if (argv1 != argv1_buf )
11351157 wasm_runtime_free (argv1 );
1158+
11361159 if (clear_wasi_proc_exit_exception (module_inst ))
1137- return true;
1138- return false;
1160+ ret = true;
1161+ else
1162+ ret = false;
11391163 }
11401164
1165+ #if WASM_ENABLE_DUMP_CALL_STACK != 0
1166+ if (!ret ) {
1167+ aot_dump_call_stack (exec_env );
1168+ }
1169+ #endif
1170+
1171+ #if (WASM_ENABLE_DUMP_CALL_STACK != 0 ) || (WASM_ENABLE_PERF_PROFILING != 0 )
1172+ aot_free_frame (exec_env );
1173+ #endif
1174+ if (!ret )
1175+ return ret ;
1176+
11411177 /* Get extra result values */
11421178 switch (func_type -> types [func_type -> param_count ]) {
11431179 case VALUE_TYPE_I32 :
@@ -1161,10 +1197,28 @@ aot_call_function(WASMExecEnv *exec_env,
11611197 return true;
11621198 }
11631199 else {
1200+ #if (WASM_ENABLE_DUMP_CALL_STACK != 0 ) || (WASM_ENABLE_PERF_PROFILING != 0 )
1201+ if (!aot_alloc_frame (exec_env , function -> func_index )) {
1202+ return false;
1203+ }
1204+ #endif
1205+
11641206 ret = invoke_native_internal (exec_env , function -> u .func .func_ptr ,
11651207 func_type , NULL , NULL , argv , argc , argv );
1208+
11661209 if (clear_wasi_proc_exit_exception (module_inst ))
1167- return true;
1210+ ret = true;
1211+
1212+ #if WASM_ENABLE_DUMP_CALL_STACK != 0
1213+ if (aot_get_exception (module_inst )) {
1214+ aot_dump_call_stack (exec_env );
1215+ }
1216+ #endif
1217+
1218+ #if (WASM_ENABLE_DUMP_CALL_STACK != 0 ) || (WASM_ENABLE_PERF_PROFILING != 0 )
1219+ aot_free_frame (exec_env );
1220+ #endif
1221+
11681222 return ret && !aot_get_exception (module_inst ) ? true : false;
11691223 }
11701224}
@@ -2224,3 +2278,134 @@ aot_get_module_inst_mem_consumption(const AOTModuleInstance *module_inst,
22242278}
22252279#endif /* end of (WASM_ENABLE_MEMORY_PROFILING != 0)
22262280 || (WASM_ENABLE_MEMORY_TRACING != 0) */
2281+
2282+ #if (WASM_ENABLE_DUMP_CALL_STACK != 0 ) || (WASM_ENABLE_PERF_PROFILING != 0 )
2283+ static const char *
2284+ get_func_name_from_index (const AOTModuleInstance * module_inst ,
2285+ uint32 func_index )
2286+ {
2287+ const char * func_name = NULL ;
2288+ AOTModule * module = module_inst -> aot_module .ptr ;
2289+
2290+ if (func_index < module -> import_func_count ) {
2291+ func_name = module -> import_funcs [func_index ].func_name ;
2292+ }
2293+ else {
2294+ uint32 i ;
2295+
2296+ for (i = 0 ; i < module -> export_count ; i ++ ) {
2297+ AOTExport export = module -> exports [i ];
2298+ if (export .index == func_index
2299+ && export .kind == EXPORT_KIND_FUNC ) {
2300+ func_name = export .name ;
2301+ break ;
2302+ }
2303+ }
2304+ }
2305+
2306+ return func_name ;
2307+ }
2308+
2309+ bool
2310+ aot_alloc_frame (WASMExecEnv * exec_env , uint32 func_index )
2311+ {
2312+ AOTFrame * frame =
2313+ wasm_exec_env_alloc_wasm_frame (exec_env , sizeof (AOTFrame ));
2314+ #if WASM_ENABLE_PERF_PROFILING != 0
2315+ AOTModuleInstance * module_inst =
2316+ (AOTModuleInstance * )exec_env -> module_inst ;
2317+ AOTFuncPerfProfInfo * func_perf_prof =
2318+ (AOTFuncPerfProfInfo * )module_inst -> func_perf_profilings .ptr + func_index ;
2319+ #endif
2320+
2321+ if (!frame ) {
2322+ aot_set_exception ((AOTModuleInstance * )exec_env -> module_inst ,
2323+ "auxiliary call stack overflow" );
2324+ return false;
2325+ }
2326+
2327+ #if WASM_ENABLE_PERF_PROFILING != 0
2328+ frame -> time_started = os_time_get_boot_microsecond ();
2329+ frame -> func_perf_prof_info = func_perf_prof ;
2330+ #endif
2331+
2332+ frame -> prev_frame = (AOTFrame * )exec_env -> cur_frame ;
2333+ exec_env -> cur_frame = (struct WASMInterpFrame * )frame ;
2334+
2335+ frame -> func_index = func_index ;
2336+ return true;
2337+ }
2338+
2339+ void
2340+ aot_free_frame (WASMExecEnv * exec_env )
2341+ {
2342+ AOTFrame * cur_frame = (AOTFrame * )exec_env -> cur_frame ;
2343+ AOTFrame * prev_frame = cur_frame -> prev_frame ;
2344+
2345+ #if WASM_ENABLE_PERF_PROFILING != 0
2346+ cur_frame -> func_perf_prof_info -> total_exec_time +=
2347+ os_time_get_boot_microsecond () - cur_frame -> time_started ;
2348+ cur_frame -> func_perf_prof_info -> total_exec_cnt ++ ;
2349+ #endif
2350+
2351+ wasm_exec_env_free_wasm_frame (exec_env , cur_frame );
2352+ exec_env -> cur_frame = (struct WASMInterpFrame * )prev_frame ;
2353+ }
2354+ #endif /* end of (WASM_ENABLE_DUMP_CALL_STACK != 0)
2355+ || (WASM_ENABLE_PERF_PROFILING != 0) */
2356+
2357+ #if WASM_ENABLE_DUMP_CALL_STACK != 0
2358+ void
2359+ aot_dump_call_stack (WASMExecEnv * exec_env )
2360+ {
2361+ AOTFrame * cur_frame = (AOTFrame * )exec_env -> cur_frame ;
2362+ AOTModuleInstance * module_inst =
2363+ (AOTModuleInstance * )exec_env -> module_inst ;
2364+ const char * func_name ;
2365+ uint32 n = 0 ;
2366+
2367+ os_printf ("\n" );
2368+ while (cur_frame ) {
2369+ func_name =
2370+ get_func_name_from_index (module_inst , cur_frame -> func_index );
2371+
2372+ /* function name not exported, print number instead */
2373+ if (func_name == NULL ) {
2374+ os_printf ("#%02d $f%d \n" , n , cur_frame -> func_index );
2375+ }
2376+ else {
2377+ os_printf ("#%02d %s \n" , n , func_name );
2378+ }
2379+
2380+ cur_frame = cur_frame -> prev_frame ;
2381+ n ++ ;
2382+ }
2383+ os_printf ("\n" );
2384+ }
2385+ #endif /* end of WASM_ENABLE_DUMP_CALL_STACK */
2386+
2387+ #if WASM_ENABLE_PERF_PROFILING != 0
2388+ void
2389+ aot_dump_perf_profiling (const AOTModuleInstance * module_inst )
2390+ {
2391+ AOTFuncPerfProfInfo * perf_prof = (AOTFuncPerfProfInfo * )
2392+ module_inst -> func_perf_profilings .ptr ;
2393+ AOTModule * module = (AOTModule * )module_inst -> aot_module .ptr ;
2394+ uint32 total_func_count = module -> import_func_count + module -> func_count , i ;
2395+ const char * func_name ;
2396+
2397+ os_printf ("Performance profiler data:\n" );
2398+ for (i = 0 ; i < total_func_count ; i ++ , perf_prof ++ ) {
2399+ func_name = get_func_name_from_index (module_inst , i );
2400+
2401+ if (func_name )
2402+ os_printf (" func %s, execution time: %.3f ms, execution count: %d times\n" ,
2403+ func_name , perf_prof -> total_exec_time / 1000.0f ,
2404+ perf_prof -> total_exec_cnt );
2405+ else
2406+ os_printf (" func %d, execution time: %.3f ms, execution count: %d times\n" ,
2407+ i , perf_prof -> total_exec_time / 1000.0f ,
2408+ perf_prof -> total_exec_cnt );
2409+ }
2410+ }
2411+ #endif /* end of WASM_ENABLE_PERF_PROFILING */
0 commit comments