From e03324d772bbe880f2c01bfc743e34c1a4f77d3d Mon Sep 17 00:00:00 2001 From: JUNG DONG-HEON Date: Thu, 9 Jan 2020 16:38:00 +0900 Subject: [Tizen] Reduce arm_phdr_cb call overhead - 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/libunwind/include/tdep-arm/libunwind_i.h | 3 ++ src/pal/src/libunwind/src/arm/Gex_tables.c | 45 +++++++++++++++++++++- src/pal/src/libunwind/src/arm/Gglobal.c | 1 + 3 files changed, 48 insertions(+), 1 deletion(-) diff --git a/src/pal/src/libunwind/include/tdep-arm/libunwind_i.h b/src/pal/src/libunwind/include/tdep-arm/libunwind_i.h index 2602f41c4f..608107bfd3 100644 --- a/src/pal/src/libunwind/include/tdep-arm/libunwind_i.h +++ b/src/pal/src/libunwind/include/tdep-arm/libunwind_i.h @@ -254,6 +254,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) @@ -296,6 +298,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); diff --git a/src/pal/src/libunwind/src/arm/Gex_tables.c b/src/pal/src/libunwind/src/arm/Gex_tables.c index d6573a65e0..1e7b0044b9 100644 --- a/src/pal/src/libunwind/src/arm/Gex_tables.c +++ b/src/pal/src/libunwind/src/arm/Gex_tables.c @@ -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 */ diff --git a/src/pal/src/libunwind/src/arm/Gglobal.c b/src/pal/src/libunwind/src/arm/Gglobal.c index 7b93fbd89a..82428e31cd 100644 --- a/src/pal/src/libunwind/src/arm/Gglobal.c +++ b/src/pal/src/libunwind/src/arm/Gglobal.c @@ -55,6 +55,7 @@ tdep_init (void) dwarf_init (); + arm_cb_cache_data_init (); #ifndef UNW_REMOTE_ONLY arm_local_addr_space_init (); #endif -- cgit v1.2.3