mirror of
https://github.com/tobast/libunwind-eh_elf.git
synced 2025-01-09 10:53:43 +01:00
[x86-64] Add a known good address cache.
This improves the performance of Lperf-simple from 500ns to 195ns on the avg. Signed-off-by: Arun Sharma <arun.sharma@google.com>
This commit is contained in:
parent
96969f8494
commit
795529eee3
3 changed files with 44 additions and 1 deletions
|
@ -50,6 +50,7 @@ struct unw_addr_space
|
|||
unw_word_t dyn_generation; /* see dyn-common.h */
|
||||
unw_word_t dyn_info_list_addr; /* (cached) dyn_info_list_addr */
|
||||
struct dwarf_rs_cache global_cache;
|
||||
int validate;
|
||||
};
|
||||
|
||||
struct cursor
|
||||
|
|
|
@ -107,6 +107,43 @@ get_dyn_info_list_addr (unw_addr_space_t as, unw_word_t *dyn_info_list_addr,
|
|||
#define PAGE_SIZE 4096
|
||||
#define PAGE_START(a) ((a) & ~(PAGE_SIZE-1))
|
||||
|
||||
/* Cache of already validated addresses */
|
||||
#define NLGA 4
|
||||
static unw_word_t last_good_addr[NLGA];
|
||||
static int lga_victim;
|
||||
|
||||
static int
|
||||
validate_mem (unw_word_t addr)
|
||||
{
|
||||
int i, victim;
|
||||
|
||||
addr = PAGE_START(addr);
|
||||
|
||||
for (i = 0; i < NLGA; i++) {
|
||||
if (last_good_addr[i] && (addr == last_good_addr[i]))
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (msync((void *) addr, 1, MS_SYNC) == -1)
|
||||
return -1;
|
||||
|
||||
victim = lga_victim;
|
||||
for (i = 0; i < NLGA; i++) {
|
||||
if (!last_good_addr[victim]) {
|
||||
last_good_addr[victim++] = addr;
|
||||
return 0;
|
||||
}
|
||||
victim = (victim + 1) % NLGA;
|
||||
}
|
||||
|
||||
/* All slots full. Evict the victim. */
|
||||
last_good_addr[victim] = addr;
|
||||
victim = (victim + 1) % NLGA;
|
||||
lga_victim = victim;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
access_mem (unw_addr_space_t as, unw_word_t addr, unw_word_t *val, int write,
|
||||
void *arg)
|
||||
|
@ -119,7 +156,7 @@ access_mem (unw_addr_space_t as, unw_word_t addr, unw_word_t *val, int write,
|
|||
else
|
||||
{
|
||||
/* validate address */
|
||||
if (msync(PAGE_START(addr), 1, MS_SYNC) == -1)
|
||||
if (as->validate && validate_mem(addr))
|
||||
return -1;
|
||||
*val = *(unw_word_t *) addr;
|
||||
Debug (16, "mem[%016lx] -> %lx\n", addr, *val);
|
||||
|
@ -212,6 +249,10 @@ x86_64_local_addr_space_init (void)
|
|||
local_addr_space.acc.resume = x86_64_local_resume;
|
||||
local_addr_space.acc.get_proc_name = get_static_proc_name;
|
||||
unw_flush_cache (&local_addr_space, 0, 0);
|
||||
|
||||
local_addr_space.validate = 0;
|
||||
bzero(last_good_addr, sizeof(unw_word_t) * NLGA);
|
||||
lga_victim = 0;
|
||||
}
|
||||
|
||||
#endif /* !UNW_REMOTE_ONLY */
|
||||
|
|
|
@ -40,6 +40,7 @@ unw_is_signal_frame (unw_cursor_t *cursor)
|
|||
|
||||
as = c->dwarf.as;
|
||||
a = unw_get_accessors (as);
|
||||
as->validate = 1; /* Don't trust the ip */
|
||||
arg = c->dwarf.as_arg;
|
||||
|
||||
/* Check if RIP points at sigreturn sequence.
|
||||
|
|
Loading…
Reference in a new issue