]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Slightly improve x86 unwind intensive workload.
authorPhilippe Waroquiers <philippe.waroquiers@skynet.be>
Tue, 26 May 2015 21:26:39 +0000 (21:26 +0000)
committerPhilippe Waroquiers <philippe.waroquiers@skynet.be>
Tue, 26 May 2015 21:26:39 +0000 (21:26 +0000)
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

coregrind/m_debuginfo/debuginfo.c
coregrind/m_stacktrace.c
coregrind/pub_core_debuginfo.h

index 31fd369bb45895d416aaefd9f7afe2d9601f6749..15f1603505a64289ac948c13dc7f7c865a08369d 100644 (file)
 /*--- 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;
+}
+
 
 /*--------------------------------------------------------------*/
 /*---                                                        ---*/
index b2d188629f27bb38f36e891358a7d0af67a4f1b8..d1b8c4d2aca5f5bad2094573c5409a7b9b18bd38 100644 (file)
@@ -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;
index ce1b199fdfecce506d85c97b75ad669cf8ad1bb0..98029ab79eaa7c75fc74cd85f418d7c379a477f8 100644 (file)
@@ -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,