|
From: <sv...@va...> - 2008-10-15 16:44:06
|
Author: sewardj
Date: 2008-10-15 17:38:03 +0100 (Wed, 15 Oct 2008)
New Revision: 8674
Log:
Speedups to stack unwinding on amd64-linux. Back out the cacheing
mechanism introduced by r8668 and replace it with something more
powerful, that caches IP-to-DiCfSI mappings for the entire system
instead of on a per-DebugInfo basis.
To make this safe, some previously unstated invariants relating to
DiCfSI records have been documented and are now checked after every
debuginfo load/unload. See the comment labelled
Comment_on_IMPORTANT_CFSI_REPRESENTATIONAL_INVARIANTS in
priv_storage.h.
Modified:
branches/YARD/coregrind/m_debuginfo/debuginfo.c
branches/YARD/coregrind/m_debuginfo/misc.c
branches/YARD/coregrind/m_debuginfo/priv_storage.h
branches/YARD/coregrind/m_debuginfo/storage.c
branches/YARD/coregrind/m_main.c
branches/YARD/coregrind/pub_core_debuginfo.h
Modified: branches/YARD/coregrind/m_debuginfo/debuginfo.c
===================================================================
--- branches/YARD/coregrind/m_debuginfo/debuginfo.c 2008-10-15 16:30:55 UTC (rev 8673)
+++ branches/YARD/coregrind/m_debuginfo/debuginfo.c 2008-10-15 16:38:03 UTC (rev 8674)
@@ -99,6 +99,13 @@
/*------------------------------------------------------------*/
+/*--- fwdses ---*/
+/*------------------------------------------------------------*/
+
+static void cfsi_cache__invalidate ( void );
+
+
+/*------------------------------------------------------------*/
/*--- Root structure ---*/
/*------------------------------------------------------------*/
@@ -171,8 +178,8 @@
di->memname = memname ? ML_(dinfo_strdup)("di.debuginfo.aDI.3", memname)
: NULL;
- /* Everything else -- pointers, sizes, arrays -- is zeroed by
- ML_(dinfo_zalloc). Now set up the debugging-output flags. */
+ /* Everything else -- pointers, sizes, arrays -- is zeroed by calloc.
+ Now set up the debugging-output flags. */
traceme
= VG_(string_match)( VG_(clo_trace_symtab_patt), filename )
|| (memname && VG_(string_match)( VG_(clo_trace_symtab_patt),
@@ -314,10 +321,11 @@
/* Repeatedly scan debugInfo_list, looking for DebugInfos with text
AVMAs intersecting [start,start+length), and call discard_DebugInfo
to get rid of them. This modifies the list, hence the multiple
- iterations.
+ iterations. Returns True iff any such DebugInfos were found.
*/
-static void discard_syms_in_range ( Addr start, SizeT length )
+static Bool discard_syms_in_range ( Addr start, SizeT length )
{
+ Bool anyFound = False;
Bool found;
DebugInfo* curr;
@@ -341,8 +349,11 @@
}
if (!found) break;
+ anyFound = True;
discard_DebugInfo( curr );
}
+
+ return anyFound;
}
@@ -472,8 +483,86 @@
}
+/* Debuginfo reading for 'di' has just been successfully completed.
+ Check that the invariants stated in
+ "Comment_on_IMPORTANT_CFSI_REPRESENTATIONAL_INVARIANTS" in
+ priv_storage.h are observed. */
+static void check_CFSI_related_invariants ( DebugInfo* di )
+{
+ DebugInfo* di2 = NULL;
+ vg_assert(di);
+ /* This fn isn't called until after debuginfo for this object has
+ been successfully read. And that shouldn't happen until we have
+ both a r-x and rw- mapping for the object. Hence: */
+ vg_assert(di->have_rx_map);
+ vg_assert(di->have_rw_map);
+ /* degenerate case: r-x section is empty */
+ if (di->rx_map_size == 0) {
+ vg_assert(di->cfsi == NULL);
+ return;
+ }
+ /* normal case: r-x section is nonempty */
+ /* invariant (0) */
+ vg_assert(di->rx_map_size > 0);
+ /* invariant (1) */
+ for (di2 = debugInfo_list; di2; di2 = di2->next) {
+ if (di2 == di)
+ continue;
+ if (di2->rx_map_size == 0)
+ continue;
+ vg_assert(di->rx_map_avma + di->rx_map_size <= di2->rx_map_avma
+ || di2->rx_map_avma + di2->rx_map_size <= di->rx_map_avma);
+ }
+ di2 = NULL;
+ /* invariant (2) */
+ if (di->cfsi) {
+ vg_assert(di->cfsi_minavma <= di->cfsi_maxavma); /* duh! */
+ vg_assert(di->cfsi_minavma >= di->rx_map_avma);
+ vg_assert(di->cfsi_maxavma < di->rx_map_avma + di->rx_map_size);
+ }
+ /* invariants (3) and (4) */
+ if (di->cfsi) {
+ Word i;
+ vg_assert(di->cfsi_used > 0);
+ vg_assert(di->cfsi_size > 0);
+ for (i = 0; i < di->cfsi_used; i++) {
+ DiCfSI* cfsi = &di->cfsi[i];
+ vg_assert(cfsi->len > 0);
+ vg_assert(cfsi->base >= di->cfsi_minavma);
+ vg_assert(cfsi->base + cfsi->len - 1 <= di->cfsi_maxavma);
+ if (i > 0) {
+ DiCfSI* cfsip = &di->cfsi[i-1];
+ vg_assert(cfsip->base + cfsip->len <= cfsi->base);
+ }
+ }
+ } else {
+ vg_assert(di->cfsi_used == 0);
+ vg_assert(di->cfsi_size == 0);
+ }
+}
+
+
/*--------------------------------------------------------------*/
/*--- ---*/
+/*--- TOP LEVEL: INITIALISE THE DEBUGINFO SYSTEM ---*/
+/*--- ---*/
+/*--------------------------------------------------------------*/
+
+void VG_(di_initialise) ( void )
+{
+ /* There's actually very little to do here, since everything
+ centers around the DebugInfos in debugInfo_list, they are
+ created and destroyed on demand, and each one is treated more or
+ less independently. */
+ vg_assert(debugInfo_list == NULL);
+
+ /* flush the CFI fast query cache. */
+ cfsi_cache__invalidate();
+}
+
+
+/*--------------------------------------------------------------*/
+/*--- ---*/
/*--- TOP LEVEL: NOTIFICATION (ACQUIRE/DISCARD INFO) (LINUX) ---*/
/*--- ---*/
/*--------------------------------------------------------------*/
@@ -695,6 +784,9 @@
/* .. and acquire new info. */
ok = ML_(read_elf_debug_info)( di );
+ /* .. and invalidate the CFI unwind cache. */
+ cfsi_cache__invalidate();
+
if (ok) {
TRACE_SYMTAB("\n------ Canonicalising the "
"acquired info ------\n");
@@ -705,11 +797,16 @@
VG_(redir_notify_new_DebugInfo)( di );
/* Note that we succeeded */
di->have_dinfo = True;
+ /* Check invariants listed in
+ Comment_on_IMPORTANT_REPRESENTATIONAL_INVARIANTS in
+ priv_storage.h. */
+ check_CFSI_related_invariants(di);
} else {
TRACE_SYMTAB("\n------ ELF reading failed ------\n");
/* Something went wrong (eg. bad ELF file). Should we delete
this DebugInfo? No - it contains info on the rw/rx
mappings, at least. */
+ vg_assert(di->have_dinfo == False);
}
TRACE_SYMTAB("\n");
@@ -726,8 +823,11 @@
[a, a+len). */
void VG_(di_notify_munmap)( Addr a, SizeT len )
{
+ Bool anyFound;
if (0) VG_(printf)("DISCARD %#lx %#lx\n", a, a+len);
- discard_syms_in_range(a, len);
+ anyFound = discard_syms_in_range(a, len);
+ if (anyFound)
+ cfsi_cache__invalidate();
}
@@ -741,8 +841,11 @@
# if defined(VGP_x86_linux)
exe_ok = exe_ok || toBool(prot & VKI_PROT_READ);
# endif
- if (0 && !exe_ok)
- discard_syms_in_range(a, len);
+ if (0 && !exe_ok) {
+ Bool anyFound = discard_syms_in_range(a, len);
+ if (anyFound)
+ cfsi_cache__invalidate();
+ }
}
#endif /* defined(VGO_linux) */
@@ -771,6 +874,10 @@
Bool is_mainexe,
Bool acquire )
{
+ /* play safe; always invalidate the CFI cache. Not
+ that it should be used on AIX, but still .. */
+ cfsi_cache__invalidate();
+
if (acquire) {
Bool ok;
@@ -812,6 +919,10 @@
VG_(redir_notify_new_DebugInfo)( di );
/* Note that we succeeded */
di->have_dinfo = True;
+ /* Check invariants listed in
+ Comment_on_IMPORTANT_REPRESENTATIONAL_INVARIANTS in
+ priv_storage.h. */
+ check_CFSI_related_invariants(di);
} else {
/* Something went wrong (eg. bad XCOFF file). */
discard_DebugInfo( di );
@@ -822,8 +933,11 @@
/* Dump all the debugInfos whose text segments intersect
code_start/code_len. */
+ /* CFI cache is always invalidated at start of this routine.
+ Hence it's safe to ignore the return value of
+ discard_syms_in_range. */
if (code_len > 0)
- discard_syms_in_range( code_start, code_len );
+ (void)discard_syms_in_range( code_start, code_len );
}
}
@@ -1511,6 +1625,122 @@
}
+/* Search all the DebugInfos in the entire system, to find the DiCfSI
+ that pertains to 'ip'.
+
+ If found, set *diP to the DebugInfo in which it resides, and
+ *ixP to the index in that DebugInfo's cfsi array.
+
+ If not found, set *diP to (DebugInfo*)1 and *ixP to zero.
+*/
+__attribute__((noinline))
+static void find_DiCfSI ( /*OUT*/DebugInfo** diP,
+ /*OUT*/Word* ixP,
+ Addr ip )
+{
+ DebugInfo* di;
+ Word i = -1;
+
+ static UWord n_search = 0;
+ static UWord n_steps = 0;
+ n_search++;
+
+ if (0) VG_(printf)("search for %#lx\n", ip);
+
+ for (di = debugInfo_list; di != NULL; di = di->next) {
+ Word j;
+ n_steps++;
+
+ /* Use the per-DebugInfo summary address ranges to skip
+ inapplicable DebugInfos quickly. */
+ if (di->cfsi_used == 0)
+ continue;
+ if (ip < di->cfsi_minavma || ip > di->cfsi_maxavma)
+ continue;
+
+ /* It might be in this DebugInfo. Search it. */
+ j = ML_(search_one_cfitab)( di, ip );
+ vg_assert(j >= -1 && j < di->cfsi_used);
+
+ if (j != -1) {
+ i = j;
+ break; /* found it */
+ }
+ }
+
+ if (i == -1) {
+
+ /* we didn't find it. */
+ *diP = (DebugInfo*)1;
+ *ixP = 0;
+
+ } else {
+
+ /* found it. */
+ /* ensure that di is 4-aligned (at least), so it can't possibly
+ be equal to (DebugInfo*)1. */
+ vg_assert(di && VG_IS_4_ALIGNED(di));
+ vg_assert(i >= 0 && i < di->cfsi_used);
+ *diP = di;
+ *ixP = i;
+
+ /* Start of performance-enhancing hack: once every 64 (chosen
+ hackily after profiling) successful searches, move the found
+ DebugInfo one step closer to the start of the list. This
+ makes future searches cheaper. For starting konqueror on
+ amd64, this in fact reduces the total amount of searching
+ done by the above find-the-right-DebugInfo loop by more than
+ a factor of 20. */
+ if ((n_search & 0xF) == 0) {
+ /* Move di one step closer to the start of the list. */
+ move_DebugInfo_one_step_forward( di );
+ }
+ /* End of performance-enhancing hack. */
+
+ if (0 && ((n_search & 0x7FFFF) == 0))
+ VG_(printf)("find_DiCfSI: %lu searches, "
+ "%lu DebugInfos looked at\n",
+ n_search, n_steps);
+
+ }
+
+}
+
+
+/* Now follows a mechanism for caching queries to find_DiCfSI, since
+ they are extremely frequent on amd64-linux, during stack unwinding.
+
+ Each cache entry binds an ip value to a (di, ix) pair. Possible
+ values:
+
+ di is non-null, ix >= 0 ==> cache slot in use, "di->cfsi[ix]"
+ di is (DebugInfo*)1 ==> cache slot in use, no associated di
+ di is NULL ==> cache slot not in use
+
+ Hence simply zeroing out the entire cache invalidates all
+ entries.
+
+ Why not map ip values directly to DiCfSI*'s? Because this would
+ cause problems if/when the cfsi array is moved due to resizing.
+ Instead we cache .cfsi array index value, which should be invariant
+ across resizing. (That said, I don't think the current
+ implementation will resize whilst during queries, since the DiCfSI
+ records are added all at once, when the debuginfo for an object is
+ read, and is not changed ever thereafter. */
+
+#define N_CFSI_CACHE 511
+
+typedef
+ struct { Addr ip; DebugInfo* di; Word ix; }
+ CFSICacheEnt;
+
+static CFSICacheEnt cfsi_cache[N_CFSI_CACHE];
+
+static void cfsi_cache__invalidate ( void ) {
+ VG_(memset)(&cfsi_cache, 0, sizeof(cfsi_cache));
+}
+
+
/* The main function for DWARF2/3 CFI-based stack unwinding.
Given an IP/SP/FP triple, produce the IP/SP/FP values for the
previous frame, if possible. */
@@ -1523,61 +1753,47 @@
Addr min_accessible,
Addr max_accessible )
{
- Bool ok;
- Int i;
- DebugInfo* si;
- DiCfSI* cfsi = NULL;
- Addr cfa, ipHere, spHere, fpHere, ipPrev, spPrev, fpPrev;
+ Bool ok;
+ DebugInfo* di;
+ DiCfSI* cfsi = NULL;
+ Addr cfa, ipHere, spHere, fpHere, ipPrev, spPrev, fpPrev;
CfiExprEvalContext eec;
- static UInt n_search = 0;
- static UInt n_steps = 0;
- n_search++;
+ static UWord n_q = 0, n_m = 0;
+ n_q++;
+ if (0 && 0 == (n_q & 0x1FFFFF))
+ VG_(printf)("QQQ %lu %lu\n", n_q, n_m);
- if (0) VG_(printf)("search for %#lx\n", *ipP);
+ { UWord hash = (*ipP) % N_CFSI_CACHE;
+ CFSICacheEnt* ce = &cfsi_cache[hash];
- for (si = debugInfo_list; si != NULL; si = si->next) {
- n_steps++;
+ if (LIKELY(ce->ip == *ipP) && LIKELY(ce->di != NULL)) {
+ /* found an entry in the cache .. */
+ } else {
+ /* not found in cache. Search and update. */
+ n_m++;
+ ce->ip = *ipP;
+ find_DiCfSI( &ce->di, &ce->ix, *ipP );
+ }
- /* Use the per-DebugInfo summary address ranges to skip
- inapplicable DebugInfos quickly. */
- if (si->cfsi_used == 0)
- continue;
- if (*ipP < si->cfsi_minavma || *ipP > si->cfsi_maxavma)
- continue;
-
- i = ML_(search_one_cfitab)( si, *ipP );
- if (i != -1) {
- vg_assert(i >= 0 && i < si->cfsi_used);
- cfsi = &si->cfsi[i];
- break;
- }
+ if (UNLIKELY(ce->di == (DebugInfo*)1)) {
+ /* no DiCfSI for this address */
+ cfsi = NULL;
+ di = NULL;
+ } else {
+ /* found a DiCfSI for this address */
+ di = ce->di;
+ cfsi = &di->cfsi[ ce->ix ];
+ }
}
- if (cfsi == NULL)
- return False;
+ if (UNLIKELY(cfsi == NULL))
+ return False; /* no info. Nothing we can do. */
- if (0 && ((n_search & 0x7FFFF) == 0))
- VG_(printf)("VG_(use_CF_info): %u searches, "
- "%u DebugInfos looked at\n",
- n_search, n_steps);
-
- /* Start of performance-enhancing hack: once every 64 (chosen
- hackily after profiling) successful searches, move the found
- DebugInfo one step closer to the start of the list. This makes
- future searches cheaper. For starting konqueror on amd64, this
- in fact reduces the total amount of searching done by the above
- find-the-right-DebugInfo loop by more than a factor of 20. */
- if ((n_search & 0x3F) == 0) {
- /* Move si one step closer to the start of the list. */
- move_DebugInfo_one_step_forward( si );
- }
- /* End of performance-enhancing hack. */
-
if (0) {
VG_(printf)("found cfisi: ");
- ML_(ppDiCfSI)(si->cfsi_exprs, cfsi);
+ ML_(ppDiCfSI)(di->cfsi_exprs, cfsi);
}
ipPrev = spPrev = fpPrev = 0;
@@ -1598,7 +1814,7 @@
case CFIC_EXPR:
if (0) {
VG_(printf)("CFIC_EXPR: ");
- ML_(ppCfiExpr)(si->cfsi_exprs, cfsi->cfa_off);
+ ML_(ppCfiExpr)(di->cfsi_exprs, cfsi->cfa_off);
VG_(printf)("\n");
}
eec.ipHere = ipHere;
@@ -1607,7 +1823,7 @@
eec.min_accessible = min_accessible;
eec.max_accessible = max_accessible;
ok = True;
- cfa = evalCfiExpr(si->cfsi_exprs, cfsi->cfa_off, &eec, &ok );
+ cfa = evalCfiExpr(di->cfsi_exprs, cfsi->cfa_off, &eec, &ok );
if (!ok) return False;
break;
default:
@@ -1637,14 +1853,14 @@
break; \
case CFIR_EXPR: \
if (0) \
- ML_(ppCfiExpr)(si->cfsi_exprs,_off); \
+ ML_(ppCfiExpr)(di->cfsi_exprs,_off); \
eec.ipHere = ipHere; \
eec.spHere = spHere; \
eec.fpHere = fpHere; \
eec.min_accessible = min_accessible; \
eec.max_accessible = max_accessible; \
ok = True; \
- _prev = evalCfiExpr(si->cfsi_exprs, _off, &eec, &ok ); \
+ _prev = evalCfiExpr(di->cfsi_exprs, _off, &eec, &ok ); \
if (!ok) return False; \
break; \
default: \
Modified: branches/YARD/coregrind/m_debuginfo/misc.c
===================================================================
--- branches/YARD/coregrind/m_debuginfo/misc.c 2008-10-15 16:30:55 UTC (rev 8673)
+++ branches/YARD/coregrind/m_debuginfo/misc.c 2008-10-15 16:38:03 UTC (rev 8674)
@@ -42,8 +42,6 @@
#include "priv_misc.h" /* self */
-/* Various functions rely on this returning zeroed memory.
- alloc_DebugInfo is one of them. */
void* ML_(dinfo_zalloc) ( HChar* cc, SizeT szB ) {
void* v;
vg_assert(szB > 0);
Modified: branches/YARD/coregrind/m_debuginfo/priv_storage.h
===================================================================
--- branches/YARD/coregrind/m_debuginfo/priv_storage.h 2008-10-15 16:30:55 UTC (rev 8673)
+++ branches/YARD/coregrind/m_debuginfo/priv_storage.h 2008-10-15 16:38:03 UTC (rev 8674)
@@ -241,8 +241,6 @@
#define SEGINFO_STRCHUNKSIZE (64*1024)
-#define N_CFSI_SEARCH_CACHE 8
-
struct _DebugInfo {
/* Admin stuff */
@@ -300,7 +298,46 @@
in some obscure circumstances (to do with data/sdata/bss) it is
possible for the mapping to be present but have zero size.
Certainly text_ is mandatory on all platforms; not sure about
- the rest though. */
+ the rest though.
+
+ Comment_on_IMPORTANT_CFSI_REPRESENTATIONAL_INVARIANTS: we require that
+
+ either (rx_map_size == 0 && cfsi == NULL) (the degenerate case)
+
+ or the normal case, which is the AND of the following:
+ (0) rx_map_size > 0
+ (1) no two DebugInfos with rx_map_size > 0
+ have overlapping [rx_map_avma,+rx_map_size)
+ (2) [cfsi_minavma,cfsi_maxavma] does not extend
+ beyond [rx_map_avma,+rx_map_size); that is, the former is a
+ subrange or equal to the latter.
+ (3) all DiCfSI in the cfsi array all have ranges that fall within
+ [rx_map_avma,+rx_map_size).
+ (4) all DiCfSI in the cfsi array are non-overlapping
+
+ The cumulative effect of these restrictions is to ensure that
+ all the DiCfSI records in the entire system are non overlapping.
+ Hence any address falls into either exactly one DiCfSI record,
+ or none. Hence it is safe to cache the results of searches for
+ DiCfSI records. This is the whole point of these restrictions.
+ The caching of DiCfSI searches is done in VG_(use_CF_info). The
+ cache is flushed after any change to debugInfo_list. DiCfSI
+ searches are cached because they are central to stack unwinding
+ on amd64-linux.
+
+ Where are these invariants imposed and checked?
+
+ They are checked after a successful read of debuginfo into
+ a DebugInfo*, in check_CFSI_related_invariants.
+
+ (1) is not really imposed anywhere. We simply assume that the
+ kernel will not map the text segments from two different objects
+ into the same space. Sounds reasonable.
+
+ (2) follows from (4) and (3). It is ensured by canonicaliseCFI.
+ (3) is ensured by ML_(addDiCfSI).
+ (4) is ensured by canonicaliseCFI.
+ */
/* .text */
Bool text_present;
Addr text_avma;
@@ -364,20 +401,11 @@
records require any expression nodes, they are stored in
cfsi_exprs. */
DiCfSI* cfsi;
- UWord cfsi_used;
- UWord cfsi_size;
+ UInt cfsi_used;
+ UInt cfsi_size;
Addr cfsi_minavma;
Addr cfsi_maxavma;
XArray* cfsi_exprs; /* XArray of CfiExpr */
- /* Stack unwinding on amd64 causes a lot of searching in .cfsi to
- find the DiCfSI record that covers a particular address. To
- speed up the searches we add a small (8-entry) cache containing
- cached results from ML_(search_one_cfitab). This speeds up the
- searching by about a factor of 3 and overall increases the stack
- unwind speed by about 50% on amd64-linux on large C++ apps. */
- UWord cfsi_search_cache_used; /* 0 .. N_CFSI_SEARCH_CACHE */
- struct { Addr aMin; Addr aMax; Word ix; }
- cfsi_search_cache[N_CFSI_SEARCH_CACHE];
/* Expandable arrays of characters -- the string table. Pointers
into this are stable (the arrays are not reallocated). */
@@ -475,7 +503,7 @@
/* Find a CFI-table index containing the specified pointer, or -1 if
not found. Binary search. */
-extern Word ML_(search_one_cfitab) ( struct _DebugInfo* di, Addr ptr );
+extern Int ML_(search_one_cfitab) ( struct _DebugInfo* di, Addr ptr );
/* ------ Misc ------ */
Modified: branches/YARD/coregrind/m_debuginfo/storage.c
===================================================================
--- branches/YARD/coregrind/m_debuginfo/storage.c 2008-10-15 16:30:55 UTC (rev 8673)
+++ branches/YARD/coregrind/m_debuginfo/storage.c 2008-10-15 16:38:03 UTC (rev 8674)
@@ -365,9 +365,6 @@
ML_(ppDiCfSI)(di->cfsi_exprs, cfsi);
}
- /* invalidate the lookup cache */
- di->cfsi_search_cache_used = 0;
-
/* sanity */
vg_assert(cfsi->len > 0);
/* If this fails, the implication is you have a single procedure
@@ -1288,11 +1285,8 @@
di->cfsi_maxavma = here_max;
}
- /* invalidate the lookup cache */
- di->cfsi_search_cache_used = 0;
-
if (di->trace_cfi)
- VG_(printf)("canonicaliseCfiSI: %ld entries, %#lx .. %#lx\n",
+ VG_(printf)("canonicaliseCfiSI: %d entries, %#lx .. %#lx\n",
di->cfsi_used,
di->cfsi_minavma, di->cfsi_maxavma);
@@ -1426,12 +1420,11 @@
/* Find a CFI-table index containing the specified pointer, or -1
if not found. Binary search. */
-__attribute__((noinline))
-static
-Word search_one_cfitab_WRK ( struct _DebugInfo* di, Addr ptr )
+
+Int ML_(search_one_cfitab) ( struct _DebugInfo* di, Addr ptr )
{
Addr a_mid_lo, a_mid_hi;
- Word mid, size,
+ Int mid, size,
lo = 0,
hi = di->cfsi_used-1;
while (True) {
@@ -1449,57 +1442,7 @@
}
}
-/* Find the CFI-table index containing the specified pointer,
- or -1 if not found. It uses search_one_cfitab_WRK to do the
- real work, but caches the results so as to avoid calling
- search_one_cfitab_WRK nost of the time. */
-Word ML_(search_one_cfitab) ( struct _DebugInfo* di, Addr ptr )
-{
- static UWord nq = 0;
- static UWord nm = 0;
- Word i, w;
-
- if (0 && 0 == (nq & 0x3FFFF))
- VG_(printf)("ZZZZZ %lu qs %lu misses\n", nq,nm);
-
- nq++;
- /* Check the cache first */
- for (i = 0; i < di->cfsi_search_cache_used; i++) {
- if (di->cfsi_search_cache[i].aMin <= ptr
- && ptr <= di->cfsi_search_cache[i].aMax) {
- /* found it. Once in every 16 searches, move the found element
- one step closer to the front. */
- if (i > 0 && 0 == (nq & 0xF)) {
- __typeof__(di->cfsi_search_cache[0]) tmp;
- tmp = di->cfsi_search_cache[i-1];
- di->cfsi_search_cache[i-1] = di->cfsi_search_cache[i];
- di->cfsi_search_cache[i] = tmp;
- i--;
- }
- return di->cfsi_search_cache[i].ix;
- }
- }
- /* not found in the cache; do slow search */
- nm++;
- w = search_one_cfitab_WRK(di, ptr);
- if (w >= 0) {
- /* We got a result, so update the cache. Slide all entries
- along one and insert new one at [0]. */
- for (i = N_CFSI_SEARCH_CACHE-1; i >= 1; i--) {
- di->cfsi_search_cache[i] = di->cfsi_search_cache[i-1];
- }
- if (di->cfsi_search_cache_used < N_CFSI_SEARCH_CACHE)
- di->cfsi_search_cache_used++;
- tl_assert(di->cfsi[w].len > 0);
- di->cfsi_search_cache[0].aMin = di->cfsi[w].base;
- di->cfsi_search_cache[0].aMax = di->cfsi[w].base + di->cfsi[w].len - 1;
- di->cfsi_search_cache[0].ix = w;
- }
- return w;
-}
-
-
/*--------------------------------------------------------------------*/
/*--- end ---*/
/*--------------------------------------------------------------------*/
Modified: branches/YARD/coregrind/m_main.c
===================================================================
--- branches/YARD/coregrind/m_main.c 2008-10-15 16:30:55 UTC (rev 8673)
+++ branches/YARD/coregrind/m_main.c 2008-10-15 16:38:03 UTC (rev 8674)
@@ -1345,6 +1345,12 @@
//============================================================
//--------------------------------------------------------------
+ // Initialise m_debuginfo
+ // p: dynamic memory allocation
+ VG_(debugLog)(1, "main", "Initialise m_debuginfo\n");
+ VG_(di_initialise)();
+
+ //--------------------------------------------------------------
// Look for alternative libdir
{ HChar *cp = VG_(getenv)(VALGRIND_LIB);
if (cp != NULL)
@@ -1714,6 +1720,7 @@
// p: setup_code_redirect_table [so that redirs can be recorded]
// p: mallocfree
// p: probably: setup fds and process CLOs, so that logging works
+ // p: initialise m_debuginfo
//--------------------------------------------------------------
VG_(debugLog)(1, "main", "Load initial debug info\n");
# if defined(VGO_linux)
Modified: branches/YARD/coregrind/pub_core_debuginfo.h
===================================================================
--- branches/YARD/coregrind/pub_core_debuginfo.h 2008-10-15 16:30:55 UTC (rev 8673)
+++ branches/YARD/coregrind/pub_core_debuginfo.h 2008-10-15 16:38:03 UTC (rev 8674)
@@ -39,6 +39,9 @@
#include "pub_tool_debuginfo.h"
+/* Initialise the entire module. Must be called first of all. */
+extern void VG_(di_initialise) ( void );
+
/* LINUX: Notify the debuginfo system about a new mapping, or the
disappearance of such, or a permissions change on an existing
mapping. This is the way new debug information gets loaded. If
|