Răsfoiți Sursa

Copy read only API behind a flag instead of using user defined callback

Georgii Rylov :slightly_smiling_face 10 luni în urmă
părinte
comite
32338bb7d6

+ 5 - 0
CMakeLists.txt

@@ -104,6 +104,11 @@ if (NOT DEFINED WAMR_BUILD_LIB_WASI_THREADS)
   set (WAMR_BUILD_LIB_WASI_THREADS 0)
 endif ()
 
+if (NOT DEFINED WAMR_ENABLE_COPY_CALLSTACK)
+  # Disable copy callstack by default
+  set (WAMR_ENABLE_COPY_CALLSTACK 0)
+endif()
+
 if (NOT DEFINED WAMR_BUILD_MINI_LOADER)
   # Disable wasm mini loader by default
   set (WAMR_BUILD_MINI_LOADER 0)

+ 8 - 0
build-scripts/config_common.cmake

@@ -319,6 +319,14 @@ if (WAMR_BUILD_SHARED_HEAP EQUAL 1)
   message ("     Shared heap enabled")
 endif()
 
+if (WAMR_ENABLE_COPY_CALLSTACK EQUAL 1)
+  add_definitions (-DWAMR_ENABLE_COPY_CALLSTACK=1)
+  message("      Copy callstack enabled")
+else ()
+  add_definitions (-DWAMR_ENABLE_COPY_CALLSTACK=0)
+  message("      Copy callstack disabled")
+endif()
+
 if (WAMR_BUILD_MEMORY64 EQUAL 1)
   # if native is 32-bit or cross-compiled to 32-bit
   if (NOT WAMR_BUILD_TARGET MATCHES ".*64.*")

+ 44 - 26
core/iwasm/aot/aot_runtime.c

@@ -4103,11 +4103,11 @@ aot_frame_update_profile_info(WASMExecEnv *exec_env, bool alloc_frame)
 }
 #endif /* end of WASM_ENABLE_AOT_STACK_FRAME != 0 */
 
-#if WASM_ENABLE_DUMP_CALL_STACK != 0
-void
-aot_iterate_callstack_tiny_frame(WASMExecEnv *exec_env,
-                                 const wasm_frame_callback frame_handler,
-                                 void *user_data)
+#if WAMR_ENABLE_COPY_CALLSTACK != 0
+uint32
+aot_copy_callstack_tiny_frame(WASMExecEnv *exec_env, wasm_frame_ptr_t buffer,
+    const uint32 length,
+    const uint32 skip_n)
 {
     /*
      * Note for devs: please refrain from such modifications inside of
@@ -4122,35 +4122,43 @@ aot_iterate_callstack_tiny_frame(WASMExecEnv *exec_env,
     uint8 *top = exec_env->wasm_stack.top;
     uint8 *bottom = exec_env->wasm_stack.bottom;
 
+    uint32 count = 0;
+
     bool is_top_index_in_range =
         top_boundary >= top && top >= (bottom + sizeof(AOTTinyFrame));
     if (!is_top_index_in_range) {
-        return;
+        return count;
     }
     bool is_top_aligned_with_bottom =
         (unsigned long)(top - bottom) % sizeof(AOTTinyFrame) == 0;
     if (!is_top_aligned_with_bottom) {
-        return;
+        return count;
     }
 
     AOTTinyFrame *frame = (AOTTinyFrame *)(top - sizeof(AOTTinyFrame));
     WASMCApiFrame record_frame;
-    while (frame && (uint8_t *)frame >= bottom) {
+    while (frame && (uint8_t *)frame >= bottom
+            && count < (skip_n + length)) {
+        if (count < skip_n) {
+            ++count;
+            frame -= 1;
+            continue;
+        }
         record_frame.instance = exec_env->module_inst;
         record_frame.module_offset = 0;
         record_frame.func_index = frame->func_index;
         record_frame.func_offset = frame->ip_offset;
-        if (!frame_handler(user_data, &record_frame)) {
-            break;
-        }
+        buffer[count - skip_n] = record_frame;
         frame -= 1;
+        ++count;
     }
+    return count;
 }
 
-void
-aot_iterate_callstack_standard_frame(WASMExecEnv *exec_env,
-                                     const wasm_frame_callback frame_handler,
-                                     void *user_data)
+uint32
+aot_copy_callstack_standard_frame(WASMExecEnv *exec_env, wasm_frame_ptr_t buffer,
+    const uint32 length,
+    const uint32 skip_n)
 {
     /*
      * Note for devs: please refrain from such modifications inside of
@@ -4169,17 +4177,24 @@ aot_iterate_callstack_standard_frame(WASMExecEnv *exec_env,
     uint8 *bottom = exec_env->wasm_stack.bottom;
     uint32 frame_size = (uint32)offsetof(AOTFrame, lp);
 
+    uint32 count = 0;
+
     WASMCApiFrame record_frame;
     while (cur_frame && (uint8_t *)cur_frame >= bottom
-           && (uint8_t *)cur_frame + frame_size <= top_boundary) {
+           && (uint8_t *)cur_frame + frame_size <= top_boundary
+           && count < (skip_n + length)) {
+        if (count < skip_n) {
+            ++count;
+            cur_frame = cur_frame->prev_frame;
+            continue;
+        }
         record_frame.instance = module_inst;
         record_frame.module_offset = 0;
         record_frame.func_index = (uint32)cur_frame->func_index;
         record_frame.func_offset = (uint32)cur_frame->ip_offset;
-        if (!frame_handler(user_data, &record_frame)) {
-            break;
-        }
+        buffer[count - skip_n] = record_frame;
         cur_frame = cur_frame->prev_frame;
+        ++count;
     }
 #else
 /*
@@ -4189,9 +4204,11 @@ aot_iterate_callstack_standard_frame(WASMExecEnv *exec_env,
 #endif
 }
 
-void
-aot_iterate_callstack(WASMExecEnv *exec_env,
-                      const wasm_frame_callback frame_handler, void *user_data)
+
+uint32
+aot_copy_callstack(WASMExecEnv *exec_env, wasm_frame_ptr_t buffer,
+    const uint32 length,
+    const uint32 skip_n)
 {
     /*
      * Note for devs: please refrain from such modifications inside of
@@ -4203,14 +4220,15 @@ aot_iterate_callstack(WASMExecEnv *exec_env,
      * wasm_export.h
      */
     if (!is_tiny_frame(exec_env)) {
-        aot_iterate_callstack_standard_frame(exec_env, frame_handler,
-                                             user_data);
+        return aot_copy_callstack_standard_frame(exec_env, buffer, length, skip_n);
     }
     else {
-        aot_iterate_callstack_tiny_frame(exec_env, frame_handler, user_data);
+        return aot_copy_callstack_tiny_frame(exec_env, buffer, length, skip_n);
     }
 }
+#endif // WAMR_ENABLE_COPY_CALLSTACK
 
+#if WASM_ENABLE_DUMP_CALL_STACK != 0
 bool
 aot_create_call_stack(struct WASMExecEnv *exec_env)
 {
@@ -4391,7 +4409,7 @@ aot_dump_call_stack(WASMExecEnv *exec_env, bool print, char *buf, uint32 len)
 
     return total_len + 1;
 }
-#endif /* end of WASM_ENABLE_DUMP_CALL_STACK != 0 */
+#endif /* end of WASM_ENABLE_DUMP_CALL_STACK != 0 && WASM_ENABLE_AOT_STACK_FRAME != 0 */
 
 #if WASM_ENABLE_PERF_PROFILING != 0
 void

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

@@ -10,6 +10,7 @@
 #include "../common/wasm_runtime_common.h"
 #include "../interpreter/wasm_runtime.h"
 #include "../compilation/aot.h"
+#include "platform_common.h"
 #if WASM_ENABLE_GC != 0
 #include "gc_export.h"
 #endif
@@ -777,9 +778,12 @@ aot_frame_update_profile_info(WASMExecEnv *exec_env, bool alloc_frame);
 bool
 aot_create_call_stack(struct WASMExecEnv *exec_env);
 
-void
-aot_iterate_callstack(WASMExecEnv *exec_env,
-                      const wasm_frame_callback frame_handler, void *user_data);
+#if WAMR_ENABLE_COPY_CALLSTACK != 0
+uint32
+aot_copy_callstack(WASMExecEnv *exec_env, wasm_frame_ptr_t buffer,
+    const uint32 length,
+    const uint32 skip_n);
+#endif // WAMR_ENABLE_COPY_CALLSTACK
 
 /**
  * @brief Dump wasm call stack or get the size

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

@@ -7,6 +7,7 @@
 #include "bh_common.h"
 #include "bh_assert.h"
 #include "bh_log.h"
+#include "platform_common.h"
 #include "wasm_export.h"
 #include "wasm_native.h"
 #include "wasm_runtime_common.h"
@@ -1741,18 +1742,19 @@ wasm_runtime_destroy_exec_env(WASMExecEnv *exec_env)
     wasm_exec_env_destroy(exec_env);
 }
 
-void
-wasm_iterate_callstack(const wasm_exec_env_t exec_env,
-                       const wasm_frame_callback frame_callback,
-                       void *user_data)
+#if WAMR_ENABLE_COPY_CALLSTACK != 0
+uint32
+wasm_copy_callstack(const wasm_exec_env_t exec_env, wasm_frame_ptr_t buffer,
+                       const uint32 length,
+                       const uint32 skip_n)
 {
     /*
      * Note for devs: please refrain from such modifications inside of
-     * wasm_iterate_callstack to preserve async-signal-safety
+     * wasm_copy_callstack to preserve async-signal-safety
      * - any allocations/freeing memory
      * - dereferencing any pointers other than: exec_env, exec_env->module_inst,
      * exec_env->module_inst->module, pointers between stack's bottom and
-     * top_boundary For more details check wasm_iterate_callstack in
+     * top_boundary For more details check wasm_copy_callstack in
      * wasm_export.h
      */
 #if WASM_ENABLE_DUMP_CALL_STACK
@@ -1761,17 +1763,18 @@ wasm_iterate_callstack(const wasm_exec_env_t exec_env,
 
 #if WASM_ENABLE_INTERP != 0
     if (module_inst->module_type == Wasm_Module_Bytecode) {
-        wasm_interp_iterate_callstack(exec_env, frame_callback, user_data);
+        return wasm_interp_copy_callstack(exec_env, buffer, length, skip_n);
     }
 #endif
 
 #if WASM_ENABLE_AOT != 0
     if (module_inst->module_type == Wasm_Module_AoT) {
-        aot_iterate_callstack(exec_env, frame_callback, user_data);
+        return aot_copy_callstack(exec_env, buffer, length, skip_n);
     }
 #endif
 #endif
 }
+#endif // WAMR_ENABLE_COPY_CALLSTACK
 
 bool
 wasm_runtime_init_thread_env(void)

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

@@ -8,6 +8,7 @@
 
 #include "bh_platform.h"
 #include "bh_common.h"
+#include "platform_common.h"
 #include "wasm_exec_env.h"
 #include "wasm_native.h"
 #include "../include/wasm_export.h"
@@ -464,19 +465,6 @@ typedef struct WASMRegisteredModule {
 typedef package_type_t PackageType;
 typedef wasm_section_t WASMSection, AOTSection;
 
-typedef struct wasm_frame_t {
-    /*  wasm_instance_t */
-    void *instance;
-    uint32 module_offset;
-    uint32 func_index;
-    uint32 func_offset;
-    const char *func_name_wp;
-
-    uint32 *sp;
-    uint8 *frame_ref;
-    uint32 *lp;
-} WASMCApiFrame;
-
 #if WASM_ENABLE_JIT != 0
 typedef struct LLVMJITOptions {
     uint32 opt_level;
@@ -652,10 +640,11 @@ wasm_runtime_create_exec_env(WASMModuleInstanceCommon *module_inst,
 WASM_RUNTIME_API_EXTERN void
 wasm_runtime_destroy_exec_env(WASMExecEnv *exec_env);
 
-WASM_RUNTIME_API_EXTERN void
-wasm_iterate_callstack(const wasm_exec_env_t exec_env,
-                       const wasm_frame_callback frame_handler,
-                       void *user_data);
+#if WAMR_ENABLE_COPY_CALLSTACK != 0
+WASM_RUNTIME_API_EXTERN uint32_t
+wasm_copy_callstack(const wasm_exec_env_t exec_env, wasm_frame_ptr_t buffer,
+                       const uint32 length, const uint32 skip_n);
+#endif // WAMR_ENABLE_COPY_CALLSTACK
 
 /* See wasm_export.h for description */
 WASM_RUNTIME_API_EXTERN WASMModuleInstanceCommon *

+ 27 - 14
core/iwasm/include/wasm_export.h

@@ -126,8 +126,23 @@ typedef WASMFunctionInstanceCommon *wasm_function_inst_t;
 struct WASMMemoryInstance;
 typedef struct WASMMemoryInstance *wasm_memory_inst_t;
 
-struct wasm_frame_t;
+
+typedef struct wasm_frame_t {
+    /*  wasm_instance_t */
+    void *instance;
+    uint32_t module_offset;
+    uint32_t func_index;
+    uint32_t func_offset;
+    const char *func_name_wp;
+
+    uint32_t *sp;
+    uint8_t *frame_ref;
+    uint32_t *lp;
+} WASMCApiFrame;
+
+// #if WAMR_ENABLE_COPY_CALLSTACK != 0
 typedef struct wasm_frame_t *wasm_frame_ptr_t;
+// #endif // WAMR_ENABLE_COPY_CALLSTACK
 
 /* WASM section */
 typedef struct wasm_section_t {
@@ -867,16 +882,10 @@ wasm_runtime_create_exec_env(wasm_module_inst_t module_inst,
 WASM_RUNTIME_API_EXTERN void
 wasm_runtime_destroy_exec_env(wasm_exec_env_t exec_env);
 
-/**
- * Callback to be called on wasm_frame_t*.
- * It accepts void* as a context that can be used for closures.
- * It returns bool so the iterating can stop when the callback returns false.
- * E.g. callback that returns false after processing 100 frames
- */
-typedef bool (*wasm_frame_callback)(void *, wasm_frame_ptr_t);
 
+// #if WAMR_ENABLE_COPY_CALLSTACK != 0
 /**
- * @brief Iterate over callstack frames and execute callback on it.
+ * @brief Copy callstack frames.
  *
  * Caution: This is not a thread-safe function. Ensure the exec_env
  * is suspended before calling it from another thread.
@@ -892,12 +901,16 @@ typedef bool (*wasm_frame_callback)(void *, wasm_frame_ptr_t);
  * - exec_env->module_inst->module
  *
  * @param exec_env the execution environment that containes frames
- * @param callback the callback function provided by the user
- * @param user_data context for callback provided by the user
+ * @param buffer the buffer of size equal length * sizeof(frame) to copy frames to
+ * @param length the number of frames to copy
+ * @param skip_n the number of frames to skip from the top of the stack
+ *
+ * @return number of copied frames
  */
-WASM_RUNTIME_API_EXTERN void
-wasm_iterate_callstack(const wasm_exec_env_t exec_env,
-                       const wasm_frame_callback callback, void *user_data);
+WASM_RUNTIME_API_EXTERN uint32_t
+wasm_copy_callstack(const wasm_exec_env_t exec_env, wasm_frame_ptr_t buffer,
+                       const uint32_t length, const uint32_t skip_n);
+// #endif
 
 /**
  * Get the singleton execution environment for the instance.

+ 29 - 17
core/iwasm/interpreter/wasm_runtime.c

@@ -6,6 +6,7 @@
 #include "wasm_runtime.h"
 #include "wasm.h"
 #include "wasm_exec_env.h"
+#include "wasm_export.h"
 #include "wasm_loader.h"
 #include "wasm_interp.h"
 #include "bh_common.h"
@@ -4196,46 +4197,57 @@ wasm_get_module_inst_mem_consumption(const WASMModuleInstance *module_inst,
 #endif /* end of (WASM_ENABLE_MEMORY_PROFILING != 0) \
                  || (WASM_ENABLE_MEMORY_TRACING != 0) */
 
-#if WASM_ENABLE_DUMP_CALL_STACK != 0
-void
-wasm_interp_iterate_callstack(WASMExecEnv *exec_env,
-                              const wasm_frame_callback frame_handler,
-                              void *user_data)
+
+#if WAMR_ENABLE_COPY_CALLSTACK != 0
+uint32
+wasm_interp_copy_callstack(WASMExecEnv *exec_env, wasm_frame_ptr_t buffer,
+                            uint32 length, uint32 skip_n)
 {
     /*
-     * Note for devs: please refrain from such modifications inside of
-     * wasm_interp_iterate_callstack
-     * - any allocations/freeing memory
-     * - dereferencing any pointers other than: exec_env, exec_env->module_inst,
-     * exec_env->module_inst->module, pointers between stack's bottom and
-     * top_boundary For more details check wasm_iterate_callstack in
-     * wasm_export.h
-     */
+    * Note for devs: please refrain from such modifications inside of
+    * wasm_interp_copy_callstack
+    * - any allocations/freeing memory
+    * - dereferencing any pointers other than: exec_env, exec_env->module_inst,
+    * exec_env->module_inst->module, pointers between stack's bottom and
+    * top_boundary For more details check wasm_copy_callstack in
+    * wasm_export.h
+    */
     WASMModuleInstance *module_inst =
         (WASMModuleInstance *)wasm_exec_env_get_module_inst(exec_env);
     WASMInterpFrame *cur_frame = wasm_exec_env_get_cur_frame(exec_env);
     uint8 *top_boundary = exec_env->wasm_stack.top_boundary;
     uint8 *bottom = exec_env->wasm_stack.bottom;
 
+    uint32 count = 0;
+
     WASMCApiFrame record_frame;
     while (cur_frame && (uint8_t *)cur_frame >= bottom
-           && (uint8_t *)cur_frame + sizeof(WASMInterpFrame) <= top_boundary) {
+        && (uint8_t *)cur_frame + sizeof(WASMInterpFrame) <= top_boundary
+        && count < (skip_n + length)) {
         if (!cur_frame->function) {
             cur_frame = cur_frame->prev_frame;
             continue;
         }
+        if (count < skip_n) {
+            ++count;
+            cur_frame = cur_frame->prev_frame;
+            continue;
+        }
         record_frame.instance = module_inst;
         record_frame.module_offset = 0;
         // It's safe to dereference module_inst->e because "e" is asigned only
         // once in wasm_instantiate
         record_frame.func_index =
             (uint32)(cur_frame->function - module_inst->e->functions);
-        if (!frame_handler(user_data, &record_frame)) {
-            break;
-        }
+        buffer[count - skip_n] = record_frame;
         cur_frame = cur_frame->prev_frame;
+        ++count;
     }
+    return count;
 }
+#endif // WAMR_ENABLE_COPY_CALLSTACK
+
+#if WASM_ENABLE_DUMP_CALL_STACK != 0
 
 bool
 wasm_interp_create_call_stack(struct WASMExecEnv *exec_env)

+ 6 - 4
core/iwasm/interpreter/wasm_runtime.h

@@ -12,6 +12,7 @@
 #include "bh_hashmap.h"
 #include "../common/wasm_runtime_common.h"
 #include "../common/wasm_exec_env.h"
+#include "wasm_export.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -731,10 +732,11 @@ wasm_get_table_inst(const WASMModuleInstance *module_inst, uint32 tbl_idx)
 
 #if WASM_ENABLE_DUMP_CALL_STACK != 0
 
-void
-wasm_interp_iterate_callstack(WASMExecEnv *exec_env,
-                              const wasm_frame_callback frame_handler,
-                              void *user_data);
+#if WAMR_ENABLE_COPY_CALLSTACK != 0
+uint32
+wasm_interp_copy_callstack(WASMExecEnv *exec_env, wasm_frame_ptr_t buffer,
+                              uint32 length, uint32 skip_n);
+#endif // WAMR_ENABLE_COPY_CALLSTACK
 
 bool
 wasm_interp_create_call_stack(struct WASMExecEnv *exec_env);