[Tizen] Reduce arm_phdr_cb call overhead
authorJUNG DONG-HEON <dheon.jung@samsung.com>
Thu, 9 Jan 2020 07:38:00 +0000 (16:38 +0900)
committerGleb Balykov <g.balykov@samsung.com>
Wed, 8 Dec 2021 16:14:52 +0000 (19:14 +0300)
- Too many calls to arm_phdr_cb even though it get the same data.
- It caches an ARM_CB_DATA for libcoreclr.so, then reuse.

src/coreclr/pal/src/libunwind/include/tdep-arm/libunwind_i.h
src/coreclr/pal/src/libunwind/src/arm/Gex_tables.c
src/coreclr/pal/src/libunwind/src/arm/Gglobal.c

index 36ceca3..75418e5 100644 (file)
@@ -257,6 +257,8 @@ dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
 #define tdep_init                       UNW_OBJ(init)
 #define arm_find_proc_info              UNW_OBJ(find_proc_info)
 #define arm_put_unwind_info             UNW_OBJ(put_unwind_info)
+#define arm_cb_cache_data_init          UNW_OBJ(cb_cache_data_init)
+
 /* Platforms that support UNW_INFO_FORMAT_TABLE need to define
    tdep_search_unwind_table.  */
 #define tdep_search_unwind_table        UNW_OBJ(search_unwind_table)
@@ -299,6 +301,7 @@ extern int arm_find_proc_info (unw_addr_space_t as, unw_word_t ip,
                                void *arg);
 extern void arm_put_unwind_info (unw_addr_space_t as,
                                   unw_proc_info_t *pi, void *arg);
+extern void arm_cb_cache_data_init (void);
 extern int tdep_search_unwind_table (unw_addr_space_t as, unw_word_t ip,
                                      unw_dyn_info_t *di, unw_proc_info_t *pi,
                                      int need_unwind_info, void *arg);
index 5eb7475..73eac24 100644 (file)
@@ -463,6 +463,16 @@ tdep_search_unwind_table (unw_addr_space_t as, unw_word_t ip,
 /**
  * Callback to dl_iterate_phdr to find infos about the ARM exidx segment.
  */
+struct arm_cb_cache_data
+{
+  unw_word_t start_ip;
+  unw_word_t end_ip;
+  unw_word_t name_ptr;
+  unw_word_t table_data;
+  unw_word_t table_len;
+};
+static struct arm_cb_cache_data g_cache_data = {0, 0, 0, 0, 0};
+
 static int
 arm_phdr_cb (struct dl_phdr_info *info, size_t size, void *data)
 {
@@ -527,7 +537,20 @@ arm_find_proc_info (unw_addr_space_t as, unw_word_t ip,
       cb_data.di.format = -1;
 
       SIGPROCMASK (SIG_SETMASK, &unwi_full_mask, &saved_mask);
-      ret = dl_iterate_phdr (arm_phdr_cb, &cb_data);
+      if (ip >= g_cache_data.start_ip && ip < g_cache_data.end_ip)
+      {
+        cb_data.di.format = UNW_INFO_FORMAT_ARM_EXIDX;
+        cb_data.di.start_ip = g_cache_data.start_ip;
+        cb_data.di.end_ip = g_cache_data.end_ip;
+        cb_data.di.u.rti.name_ptr = g_cache_data.name_ptr;
+        cb_data.di.u.rti.table_data = g_cache_data.table_data;
+        cb_data.di.u.rti.table_len = g_cache_data.table_len;
+      }
+      else
+      {
+        ret = dl_iterate_phdr (arm_phdr_cb, &cb_data);
+      }
+
       SIGPROCMASK (SIG_SETMASK, &saved_mask, NULL);
 
       if (cb_data.di.format != -1)
@@ -545,5 +568,25 @@ arm_put_unwind_info (unw_addr_space_t as, unw_proc_info_t *proc_info, void *arg)
 {
   /* it's a no-op */
 }
+
+HIDDEN void
+arm_cb_cache_data_init(void)
+{
+   struct arm_cb_data cb_data;
+   memset (&cb_data, 0, sizeof (cb_data));
+   cb_data.ip = (unw_word_t)arm_cb_cache_data_init;
+   cb_data.pi = 0;
+   cb_data.di.format = -1;
+
+  int ret = dl_iterate_phdr (arm_phdr_cb, &cb_data);
+  if (ret > 0)
+  {
+    g_cache_data.start_ip = cb_data.di.start_ip;
+    g_cache_data.end_ip = cb_data.di.end_ip;
+    g_cache_data.name_ptr = cb_data.di.u.rti.name_ptr;
+    g_cache_data.table_data = cb_data.di.u.rti.table_data;
+    g_cache_data.table_len = cb_data.di.u.rti.table_len;
+  }
+}
 #endif /* !UNW_REMOTE_ONLY */
 
index 2fb1d21..328b773 100644 (file)
@@ -55,6 +55,7 @@ tdep_init (void)
 
     dwarf_init ();
 
+    arm_cb_cache_data_init ();
 #ifndef UNW_REMOTE_ONLY
     arm_local_addr_space_init ();
 #endif