From: Philippe Waroquiers Date: Tue, 26 May 2015 21:26:39 +0000 (+0000) Subject: Slightly improve x86 unwind intensive workload. X-Git-Tag: svn/VALGRIND_3_11_0~339 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=85a86af96d17235f6eed294233ef4c1c53fbf370;p=thirdparty%2Fvalgrind.git Slightly improve x86 unwind intensive workload. e.g. perf/memrw is improved by 2% to 3% with this patch. The unwinding code on x86 is trying to unwind using either the %ebp-chain or CFI unwinding. If these 2 techniques fail, then it tries to unwind using FPO (PDB) debug info. However, unless running wine or similar, there will never be such FPO/PDB info. The function VG_(use_FPO_info) is thus called for nothing for each 'end of stack'. This function scans all the loaded di to find a debug info that has some FP, to not find anything. With this patch, the unwind code on x86 will only call VG_(use_FPO_info) if some FPO/PDB info was loaded. The fact that FPO/PDB info was loaded is cached and updated similarly to cfi cache : each time new debug info is loaded, the cache value is refreshed using the debuginfo generation. The patch also changes the name of VG_(CF_info_generation) to VG_(debuginfo_generation), as this generation is changed for any kind of load or unload of debug info, not only for CFI based debug info git-svn-id: svn://svn.valgrind.org/valgrind/trunk@15293 --- diff --git a/coregrind/m_debuginfo/debuginfo.c b/coregrind/m_debuginfo/debuginfo.c index 31fd369bb4..15f1603505 100644 --- a/coregrind/m_debuginfo/debuginfo.c +++ b/coregrind/m_debuginfo/debuginfo.c @@ -105,7 +105,7 @@ /*--- fwdses ---*/ /*------------------------------------------------------------*/ -static UInt CF_info_generation = 0; +static UInt debuginfo_generation = 0; static void cfsi_m_cache__invalidate ( void ); @@ -2645,12 +2645,12 @@ static CFSI_m_CacheEnt cfsi_m_cache[N_CFSI_M_CACHE]; static void cfsi_m_cache__invalidate ( void ) { VG_(memset)(&cfsi_m_cache, 0, sizeof(cfsi_m_cache)); - CF_info_generation++; + debuginfo_generation++; } -UInt VG_(CF_info_generation) (void) +UInt VG_(debuginfo_generation) (void) { - return CF_info_generation; + return debuginfo_generation; } static inline CFSI_m_CacheEnt* cfsi_m_cache__find ( Addr ip ) @@ -3086,6 +3086,16 @@ Bool VG_(use_FPO_info) ( /*MOD*/Addr* ipP, return True; } +Bool VG_(FPO_info_present)(void) +{ + const DebugInfo* di; + for (di = debugInfo_list; di != NULL; di = di->next) { + if (di->fpo != NULL) + return True; + } + return False; +} + /*--------------------------------------------------------------*/ /*--- ---*/ diff --git a/coregrind/m_stacktrace.c b/coregrind/m_stacktrace.c index b2d188629f..d1b8c4d2ac 100644 --- a/coregrind/m_stacktrace.c +++ b/coregrind/m_stacktrace.c @@ -129,11 +129,16 @@ static Addr fp_CF_verif_cache [N_FP_CF_VERIF]; then they will not land in the same cache bucket. */ +/* cached result of VG_(FPO_info_present)(). Refreshed each time + the fp_CF_verif_generation is different of the current debuginfo + generation. */ +static Bool FPO_info_present = False; + static UInt fp_CF_verif_generation = 0; // Our cache has to be maintained in sync with the CFI cache. -// Each time the CFI cache is changed, its generation will be incremented. +// Each time the debuginfo is changed, its generation will be incremented. // We will clear our cache when our saved generation differs from -// the CFI cache generation. +// the debuginfo generation. UInt VG_(get_StackTrace_wrk) ( ThreadId tid_if_known, /*OUT*/Addr* ips, UInt max_n_ips, @@ -226,9 +231,10 @@ UInt VG_(get_StackTrace_wrk) ( ThreadId tid_if_known, } # endif - if (UNLIKELY (fp_CF_verif_generation != VG_(CF_info_generation)())) { - fp_CF_verif_generation = VG_(CF_info_generation)(); + if (UNLIKELY (fp_CF_verif_generation != VG_(debuginfo_generation)())) { + fp_CF_verif_generation = VG_(debuginfo_generation)(); VG_(memset)(&fp_CF_verif_cache, 0, sizeof(fp_CF_verif_cache)); + FPO_info_present = VG_(FPO_info_present)(); } @@ -398,8 +404,9 @@ UInt VG_(get_StackTrace_wrk) ( ThreadId tid_if_known, } /* And, similarly, try for MSVC FPO unwind info. */ - if ( VG_(use_FPO_info)( &uregs.xip, &uregs.xsp, &uregs.xbp, - fp_min, fp_max ) ) { + if (FPO_info_present + && VG_(use_FPO_info)( &uregs.xip, &uregs.xsp, &uregs.xbp, + fp_min, fp_max ) ) { if (debug) unwind_case = "MS"; if (do_stats) stats.MS++; goto unwind_done; diff --git a/coregrind/pub_core_debuginfo.h b/coregrind/pub_core_debuginfo.h index ce1b199fdf..98029ab79e 100644 --- a/coregrind/pub_core_debuginfo.h +++ b/coregrind/pub_core_debuginfo.h @@ -142,14 +142,22 @@ extern Bool VG_(use_CF_info) ( /*MOD*/D3UnwindRegs* uregs, Addr min_accessible, Addr max_accessible ); -/* returns the "generation" of the CF info. +/* returns the "generation" of the debug info. Each time some debuginfo is changed (e.g. loaded or unloaded), - the VG_(CF_info_generation) value returned will be increased. - This can be used to flush cached information derived from the CF info. */ -extern UInt VG_(CF_info_generation) (void); + the VG_(debuginfo_generation)() value returned will be increased. + This can be used to flush cached information derived from debug + info (e.g. CFI info or FPO info or ...). */ +extern UInt VG_(debuginfo_generation) (void); +/* True if some FPO information is loaded. + It is useless to call VG_(use_FPO_info) if this returns False. + Note that the return value should preferrably be cached in + the stack unwind code, and re-queried when the debug info generation + changes. */ +extern Bool VG_(FPO_info_present)(void); + /* Use MSVC FPO data to do one step of stack unwinding. */ extern Bool VG_(use_FPO_info) ( /*MOD*/Addr* ipP, /*MOD*/Addr* spP,