Implement gdbsrv "v.info stats" command giving statistics for valgrind core + tools

* addition of VG_(needs_print_stats) in pub_tool_tooliface.h
* use the above in memcheck and helgrind
* output valgrind stats and calls print_stats in server.c



git-svn-id: svn://svn.valgrind.org/valgrind/trunk@13760
This commit is contained in:
Philippe Waroquiers 2013-12-15 20:24:43 +00:00
parent 7d40b140ac
commit 492a8ae2a2
9 changed files with 211 additions and 151 deletions

5
NEWS
View File

@ -11,6 +11,11 @@ Release 3.10.0 (?? ?????? 201?)
* ==================== OTHER CHANGES ==================== * ==================== OTHER CHANGES ====================
* New and modified GDB server monitor features:
- A new monitor command "v.info stats" that shows various valgrind core and tool
statistics.
* ==================== FIXED BUGS ==================== * ==================== FIXED BUGS ====================
The following bugs have been fixed or resolved. Note that "n-i-bz" The following bugs have been fixed or resolved. Note that "n-i-bz"

View File

@ -30,6 +30,7 @@
#include "pub_core_execontext.h" #include "pub_core_execontext.h"
#include "pub_core_syswrap.h" // VG_(show_open_fds) #include "pub_core_syswrap.h" // VG_(show_open_fds)
#include "pub_core_scheduler.h" #include "pub_core_scheduler.h"
#include "pub_core_transtab.h"
unsigned long cont_thread; unsigned long cont_thread;
unsigned long general_thread; unsigned long general_thread;
@ -216,6 +217,7 @@ int handle_gdb_valgrind_command (char *mon, OutputSink *sink_wanted_at_return)
" (with aspacemgr arg, also shows valgrind segments on log ouput)\n" " (with aspacemgr arg, also shows valgrind segments on log ouput)\n"
" v.info exectxt : show stacktraces and stats of all execontexts\n" " v.info exectxt : show stacktraces and stats of all execontexts\n"
" v.info scheduler : show valgrind thread state and stacktrace\n" " v.info scheduler : show valgrind thread state and stacktrace\n"
" v.info stats : show various valgrind and tool stats\n"
" v.set debuglog <level> : set valgrind debug log level to <level>\n" " v.set debuglog <level> : set valgrind debug log level to <level>\n"
" v.translate <addr> [<traceflags>] : debug translation of <addr> with <traceflags>\n" " v.translate <addr> [<traceflags>] : debug translation of <addr> with <traceflags>\n"
" (default traceflags 0b00100000 : show after instrumentation)\n" " (default traceflags 0b00100000 : show after instrumentation)\n"
@ -288,7 +290,7 @@ int handle_gdb_valgrind_command (char *mon, OutputSink *sink_wanted_at_return)
wcmd = strtok_r (NULL, " ", &ssaveptr); wcmd = strtok_r (NULL, " ", &ssaveptr);
switch (kwdid = VG_(keyword_id) switch (kwdid = VG_(keyword_id)
("all_errors n_errs_found last_error gdbserver_status memory" ("all_errors n_errs_found last_error gdbserver_status memory"
" scheduler open_fds exectxt", " scheduler stats open_fds exectxt",
wcmd, kwd_report_all)) { wcmd, kwd_report_all)) {
case -2: case -2:
case -1: case -1:
@ -311,6 +313,8 @@ int handle_gdb_valgrind_command (char *mon, OutputSink *sink_wanted_at_return)
VG_(gdbserver_status_output)(); VG_(gdbserver_status_output)();
break; break;
case 4: /* memory */ case 4: /* memory */
VG_(printf) ("%llu bytes have already been allocated.\n",
VG_(am_get_anonsize_total)());
VG_(print_all_arena_stats) (); VG_(print_all_arena_stats) ();
if (VG_(clo_profile_heap)) if (VG_(clo_profile_heap))
VG_(print_arena_cc_analysis) (); VG_(print_arena_cc_analysis) ();
@ -332,7 +336,18 @@ int handle_gdb_valgrind_command (char *mon, OutputSink *sink_wanted_at_return)
VG_(show_sched_status) (); VG_(show_sched_status) ();
ret = 1; ret = 1;
break; break;
case 6: /* open_fds */ case 6: /* stats */
VG_(print_translation_stats)();
VG_(print_tt_tc_stats)();
VG_(print_scheduler_stats)();
VG_(print_ExeContext_stats)( False /* with_stacktraces */ );
VG_(print_errormgr_stats)();
if (VG_(needs).print_stats) {
VG_TDICT_CALL(tool_print_stats);
}
ret = 1;
break;
case 7: /* open_fds */
if (VG_(clo_track_fds)) if (VG_(clo_track_fds))
VG_(show_open_fds) (""); VG_(show_open_fds) ("");
else else
@ -341,7 +356,7 @@ int handle_gdb_valgrind_command (char *mon, OutputSink *sink_wanted_at_return)
" to show open fds\n"); " to show open fds\n");
ret = 1; ret = 1;
break; break;
case 7: /* exectxt */ case 8: /* exectxt */
VG_(print_ExeContext_stats) (True /* with_stacktraces */); VG_(print_ExeContext_stats) (True /* with_stacktraces */);
ret = 1; ret = 1;
break; break;

View File

@ -92,6 +92,7 @@ VgNeeds VG_(needs) = {
.client_requests = False, .client_requests = False,
.syscall_wrapper = False, .syscall_wrapper = False,
.sanity_checks = False, .sanity_checks = False,
.print_stats = False,
.var_info = False, .var_info = False,
.malloc_replacement = False, .malloc_replacement = False,
.xml_output = False, .xml_output = False,
@ -294,6 +295,14 @@ void VG_(needs_sanity_checks)(
VG_(tdict).tool_expensive_sanity_check = expen; VG_(tdict).tool_expensive_sanity_check = expen;
} }
void VG_(needs_print_stats) (
void (*print_stats)(void)
)
{
VG_(needs).print_stats = True;
VG_(tdict).tool_print_stats = print_stats;
}
void VG_(needs_malloc_replacement)( void VG_(needs_malloc_replacement)(
void* (*malloc) ( ThreadId, SizeT ), void* (*malloc) ( ThreadId, SizeT ),
void* (*__builtin_new) ( ThreadId, SizeT ), void* (*__builtin_new) ( ThreadId, SizeT ),

View File

@ -88,6 +88,7 @@ typedef
Bool client_requests; Bool client_requests;
Bool syscall_wrapper; Bool syscall_wrapper;
Bool sanity_checks; Bool sanity_checks;
Bool print_stats;
Bool var_info; Bool var_info;
Bool malloc_replacement; Bool malloc_replacement;
Bool xml_output; Bool xml_output;
@ -149,6 +150,9 @@ typedef struct {
Bool (*tool_cheap_sanity_check)(void); Bool (*tool_cheap_sanity_check)(void);
Bool (*tool_expensive_sanity_check)(void); Bool (*tool_expensive_sanity_check)(void);
// VG_(needs).print_stats
void (*tool_print_stats)(void);
// VG_(needs).malloc_replacement // VG_(needs).malloc_replacement
void* (*tool_malloc) (ThreadId, SizeT); void* (*tool_malloc) (ThreadId, SizeT);
void* (*tool___builtin_new) (ThreadId, SizeT); void* (*tool___builtin_new) (ThreadId, SizeT);

View File

@ -1435,6 +1435,13 @@ problems or bugs.</para>
</para> </para>
</listitem> </listitem>
<listitem>
<para><varname>v.info stats</varname> shows various valgrind core and
tool statistics. With this, Valgrind and tool statistics can
be examined while running, even without option <option>--stats=yes</option>.
</para>
</listitem>
<listitem> <listitem>
<para><varname>v.set debuglog &lt;intvalue&gt;</varname> sets the <para><varname>v.set debuglog &lt;intvalue&gt;</varname> sets the
Valgrind debug log level to &lt;intvalue&gt;. This allows to Valgrind debug log level to &lt;intvalue&gt;. This allows to

View File

@ -62,6 +62,7 @@ debugging valgrind internals monitor commands:
(with aspacemgr arg, also shows valgrind segments on log ouput) (with aspacemgr arg, also shows valgrind segments on log ouput)
v.info exectxt : show stacktraces and stats of all execontexts v.info exectxt : show stacktraces and stats of all execontexts
v.info scheduler : show valgrind thread state and stacktrace v.info scheduler : show valgrind thread state and stacktrace
v.info stats : show various valgrind and tool stats
v.set debuglog <level> : set valgrind debug log level to <level> v.set debuglog <level> : set valgrind debug log level to <level>
v.translate <addr> [<traceflags>] : debug translation of <addr> with <traceflags> v.translate <addr> [<traceflags>] : debug translation of <addr> with <traceflags>
(default traceflags 0b00100000 : show after instrumentation) (default traceflags 0b00100000 : show after instrumentation)

View File

@ -5133,6 +5133,67 @@ static void hg_print_debug_usage ( void )
); );
} }
static void hg_print_stats (void)
{
if (1) {
VG_(printf)("\n");
HG_(ppWSUstats)( univ_lsets, "univ_lsets" );
if (HG_(clo_track_lockorders)) {
VG_(printf)("\n");
HG_(ppWSUstats)( univ_laog, "univ_laog" );
}
}
//zz VG_(printf)("\n");
//zz VG_(printf)(" hbefore: %'10lu queries\n", stats__hbefore_queries);
//zz VG_(printf)(" hbefore: %'10lu cache 0 hits\n", stats__hbefore_cache0s);
//zz VG_(printf)(" hbefore: %'10lu cache > 0 hits\n", stats__hbefore_cacheNs);
//zz VG_(printf)(" hbefore: %'10lu graph searches\n", stats__hbefore_gsearches);
//zz VG_(printf)(" hbefore: %'10lu of which slow\n",
//zz stats__hbefore_gsearches - stats__hbefore_gsearchFs);
//zz VG_(printf)(" hbefore: %'10lu stack high water mark\n",
//zz stats__hbefore_stk_hwm);
//zz VG_(printf)(" hbefore: %'10lu cache invals\n", stats__hbefore_invals);
//zz VG_(printf)(" hbefore: %'10lu probes\n", stats__hbefore_probes);
VG_(printf)("\n");
VG_(printf)(" locksets: %'8d unique lock sets\n",
(Int)HG_(cardinalityWSU)( univ_lsets ));
if (HG_(clo_track_lockorders)) {
VG_(printf)(" univ_laog: %'8d unique lock sets\n",
(Int)HG_(cardinalityWSU)( univ_laog ));
}
//VG_(printf)("L(ast)L(ock) map: %'8lu inserts (%d map size)\n",
// stats__ga_LL_adds,
// (Int)(ga_to_lastlock ? VG_(sizeFM)( ga_to_lastlock ) : 0) );
VG_(printf)(" LockN-to-P map: %'8llu queries (%llu map size)\n",
HG_(stats__LockN_to_P_queries),
HG_(stats__LockN_to_P_get_map_size)() );
VG_(printf)("string table map: %'8llu queries (%llu map size)\n",
HG_(stats__string_table_queries),
HG_(stats__string_table_get_map_size)() );
if (HG_(clo_track_lockorders)) {
VG_(printf)(" LAOG: %'8d map size\n",
(Int)(laog ? VG_(sizeFM)( laog ) : 0));
VG_(printf)(" LAOG exposition: %'8d map size\n",
(Int)(laog_exposition ? VG_(sizeFM)( laog_exposition ) : 0));
}
VG_(printf)(" locks: %'8lu acquires, "
"%'lu releases\n",
stats__lockN_acquires,
stats__lockN_releases
);
VG_(printf)(" sanity checks: %'8lu\n", stats__sanity_checks);
VG_(printf)("\n");
libhb_shutdown(True); // This in fact only print stats.
}
static void hg_fini ( Int exitcode ) static void hg_fini ( Int exitcode )
{ {
if (VG_(clo_verbosity) == 1 && !VG_(clo_xml)) { if (VG_(clo_verbosity) == 1 && !VG_(clo_xml)) {
@ -5154,65 +5215,8 @@ static void hg_fini ( Int exitcode )
if (HG_(clo_sanity_flags)) if (HG_(clo_sanity_flags))
all__sanity_check("SK_(fini)"); all__sanity_check("SK_(fini)");
if (VG_(clo_stats)) { if (VG_(clo_stats))
hg_print_stats();
if (1) {
VG_(printf)("\n");
HG_(ppWSUstats)( univ_lsets, "univ_lsets" );
if (HG_(clo_track_lockorders)) {
VG_(printf)("\n");
HG_(ppWSUstats)( univ_laog, "univ_laog" );
}
}
//zz VG_(printf)("\n");
//zz VG_(printf)(" hbefore: %'10lu queries\n", stats__hbefore_queries);
//zz VG_(printf)(" hbefore: %'10lu cache 0 hits\n", stats__hbefore_cache0s);
//zz VG_(printf)(" hbefore: %'10lu cache > 0 hits\n", stats__hbefore_cacheNs);
//zz VG_(printf)(" hbefore: %'10lu graph searches\n", stats__hbefore_gsearches);
//zz VG_(printf)(" hbefore: %'10lu of which slow\n",
//zz stats__hbefore_gsearches - stats__hbefore_gsearchFs);
//zz VG_(printf)(" hbefore: %'10lu stack high water mark\n",
//zz stats__hbefore_stk_hwm);
//zz VG_(printf)(" hbefore: %'10lu cache invals\n", stats__hbefore_invals);
//zz VG_(printf)(" hbefore: %'10lu probes\n", stats__hbefore_probes);
VG_(printf)("\n");
VG_(printf)(" locksets: %'8d unique lock sets\n",
(Int)HG_(cardinalityWSU)( univ_lsets ));
if (HG_(clo_track_lockorders)) {
VG_(printf)(" univ_laog: %'8d unique lock sets\n",
(Int)HG_(cardinalityWSU)( univ_laog ));
}
//VG_(printf)("L(ast)L(ock) map: %'8lu inserts (%d map size)\n",
// stats__ga_LL_adds,
// (Int)(ga_to_lastlock ? VG_(sizeFM)( ga_to_lastlock ) : 0) );
VG_(printf)(" LockN-to-P map: %'8llu queries (%llu map size)\n",
HG_(stats__LockN_to_P_queries),
HG_(stats__LockN_to_P_get_map_size)() );
VG_(printf)("string table map: %'8llu queries (%llu map size)\n",
HG_(stats__string_table_queries),
HG_(stats__string_table_get_map_size)() );
if (HG_(clo_track_lockorders)) {
VG_(printf)(" LAOG: %'8d map size\n",
(Int)(laog ? VG_(sizeFM)( laog ) : 0));
VG_(printf)(" LAOG exposition: %'8d map size\n",
(Int)(laog_exposition ? VG_(sizeFM)( laog_exposition ) : 0));
}
VG_(printf)(" locks: %'8lu acquires, "
"%'lu releases\n",
stats__lockN_acquires,
stats__lockN_releases
);
VG_(printf)(" sanity checks: %'8lu\n", stats__sanity_checks);
VG_(printf)("\n");
libhb_shutdown(True);
}
} }
/* FIXME: move these somewhere sane */ /* FIXME: move these somewhere sane */
@ -5305,6 +5309,8 @@ static void hg_pre_clo_init ( void )
//VG_(needs_sanity_checks) (hg_cheap_sanity_check, //VG_(needs_sanity_checks) (hg_cheap_sanity_check,
// hg_expensive_sanity_check); // hg_expensive_sanity_check);
VG_(needs_print_stats) (hg_print_stats);
VG_(needs_malloc_replacement) (hg_cli__malloc, VG_(needs_malloc_replacement) (hg_cli__malloc,
hg_cli____builtin_new, hg_cli____builtin_new,
hg_cli____builtin_vec_new, hg_cli____builtin_vec_new,

View File

@ -451,6 +451,13 @@ extern void VG_(needs_sanity_checks) (
Bool(*expensive_sanity_check)(void) Bool(*expensive_sanity_check)(void)
); );
/* Can the tool produce stats during execution? */
extern void VG_(needs_print_stats) (
// Print out tool status. Note that the stats at end of execution
// should be output by the VG_(basic_tool_funcs) "fini" function.
void (*print_stats)(void)
);
/* Do we need to see variable type and location information? */ /* Do we need to see variable type and location information? */
extern void VG_(needs_var_info) ( void ); extern void VG_(needs_var_info) ( void );

View File

@ -6539,6 +6539,98 @@ static void print_SM_info(const HChar* type, Int n_SMs)
n_SMs * sizeof(SecMap) / (1024 * 1024UL) ); n_SMs * sizeof(SecMap) / (1024 * 1024UL) );
} }
static void mc_print_stats (void)
{
SizeT max_secVBit_szB, max_SMs_szB, max_shmem_szB;
VG_(message)(Vg_DebugMsg,
" memcheck: sanity checks: %d cheap, %d expensive\n",
n_sanity_cheap, n_sanity_expensive );
VG_(message)(Vg_DebugMsg,
" memcheck: auxmaps: %lld auxmap entries (%lldk, %lldM) in use\n",
n_auxmap_L2_nodes,
n_auxmap_L2_nodes * 64,
n_auxmap_L2_nodes / 16 );
VG_(message)(Vg_DebugMsg,
" memcheck: auxmaps_L1: %lld searches, %lld cmps, ratio %lld:10\n",
n_auxmap_L1_searches, n_auxmap_L1_cmps,
(10ULL * n_auxmap_L1_cmps)
/ (n_auxmap_L1_searches ? n_auxmap_L1_searches : 1)
);
VG_(message)(Vg_DebugMsg,
" memcheck: auxmaps_L2: %lld searches, %lld nodes\n",
n_auxmap_L2_searches, n_auxmap_L2_nodes
);
print_SM_info("n_issued ", n_issued_SMs);
print_SM_info("n_deissued ", n_deissued_SMs);
print_SM_info("max_noaccess ", max_noaccess_SMs);
print_SM_info("max_undefined", max_undefined_SMs);
print_SM_info("max_defined ", max_defined_SMs);
print_SM_info("max_non_DSM ", max_non_DSM_SMs);
// Three DSMs, plus the non-DSM ones
max_SMs_szB = (3 + max_non_DSM_SMs) * sizeof(SecMap);
// The 3*sizeof(Word) bytes is the AVL node metadata size.
// The VG_ROUNDUP is because the OSet pool allocator will/must align
// the elements on pointer size.
// Note that the pool allocator has some additional small overhead
// which is not counted in the below.
// Hardwiring this logic sucks, but I don't see how else to do it.
max_secVBit_szB = max_secVBit_nodes *
(3*sizeof(Word) + VG_ROUNDUP(sizeof(SecVBitNode), sizeof(void*)));
max_shmem_szB = sizeof(primary_map) + max_SMs_szB + max_secVBit_szB;
VG_(message)(Vg_DebugMsg,
" memcheck: max sec V bit nodes: %d (%ldk, %ldM)\n",
max_secVBit_nodes, max_secVBit_szB / 1024,
max_secVBit_szB / (1024 * 1024));
VG_(message)(Vg_DebugMsg,
" memcheck: set_sec_vbits8 calls: %llu (new: %llu, updates: %llu)\n",
sec_vbits_new_nodes + sec_vbits_updates,
sec_vbits_new_nodes, sec_vbits_updates );
VG_(message)(Vg_DebugMsg,
" memcheck: max shadow mem size: %ldk, %ldM\n",
max_shmem_szB / 1024, max_shmem_szB / (1024 * 1024));
if (MC_(clo_mc_level) >= 3) {
VG_(message)(Vg_DebugMsg,
" ocacheL1: %'12lu refs %'12lu misses (%'lu lossage)\n",
stats_ocacheL1_find,
stats_ocacheL1_misses,
stats_ocacheL1_lossage );
VG_(message)(Vg_DebugMsg,
" ocacheL1: %'12lu at 0 %'12lu at 1\n",
stats_ocacheL1_find - stats_ocacheL1_misses
- stats_ocacheL1_found_at_1
- stats_ocacheL1_found_at_N,
stats_ocacheL1_found_at_1 );
VG_(message)(Vg_DebugMsg,
" ocacheL1: %'12lu at 2+ %'12lu move-fwds\n",
stats_ocacheL1_found_at_N,
stats_ocacheL1_movefwds );
VG_(message)(Vg_DebugMsg,
" ocacheL1: %'12lu sizeB %'12u useful\n",
(UWord)sizeof(OCache),
4 * OC_W32S_PER_LINE * OC_LINES_PER_SET * OC_N_SETS );
VG_(message)(Vg_DebugMsg,
" ocacheL2: %'12lu refs %'12lu misses\n",
stats__ocacheL2_refs,
stats__ocacheL2_misses );
VG_(message)(Vg_DebugMsg,
" ocacheL2: %'9lu max nodes %'9lu curr nodes\n",
stats__ocacheL2_n_nodes_max,
stats__ocacheL2_n_nodes );
VG_(message)(Vg_DebugMsg,
" niacache: %'12lu refs %'12lu misses\n",
stats__nia_cache_queries, stats__nia_cache_misses);
} else {
tl_assert(ocacheL1 == NULL);
tl_assert(ocacheL2 == NULL);
}
}
static void mc_fini ( Int exitcode ) static void mc_fini ( Int exitcode )
{ {
MC_(print_malloc_stats)(); MC_(print_malloc_stats)();
@ -6576,95 +6668,8 @@ static void mc_fini ( Int exitcode )
done_prof_mem(); done_prof_mem();
if (VG_(clo_stats)) { if (VG_(clo_stats))
SizeT max_secVBit_szB, max_SMs_szB, max_shmem_szB; mc_print_stats();
VG_(message)(Vg_DebugMsg,
" memcheck: sanity checks: %d cheap, %d expensive\n",
n_sanity_cheap, n_sanity_expensive );
VG_(message)(Vg_DebugMsg,
" memcheck: auxmaps: %lld auxmap entries (%lldk, %lldM) in use\n",
n_auxmap_L2_nodes,
n_auxmap_L2_nodes * 64,
n_auxmap_L2_nodes / 16 );
VG_(message)(Vg_DebugMsg,
" memcheck: auxmaps_L1: %lld searches, %lld cmps, ratio %lld:10\n",
n_auxmap_L1_searches, n_auxmap_L1_cmps,
(10ULL * n_auxmap_L1_cmps)
/ (n_auxmap_L1_searches ? n_auxmap_L1_searches : 1)
);
VG_(message)(Vg_DebugMsg,
" memcheck: auxmaps_L2: %lld searches, %lld nodes\n",
n_auxmap_L2_searches, n_auxmap_L2_nodes
);
print_SM_info("n_issued ", n_issued_SMs);
print_SM_info("n_deissued ", n_deissued_SMs);
print_SM_info("max_noaccess ", max_noaccess_SMs);
print_SM_info("max_undefined", max_undefined_SMs);
print_SM_info("max_defined ", max_defined_SMs);
print_SM_info("max_non_DSM ", max_non_DSM_SMs);
// Three DSMs, plus the non-DSM ones
max_SMs_szB = (3 + max_non_DSM_SMs) * sizeof(SecMap);
// The 3*sizeof(Word) bytes is the AVL node metadata size.
// The VG_ROUNDUP is because the OSet pool allocator will/must align
// the elements on pointer size.
// Note that the pool allocator has some additional small overhead
// which is not counted in the below.
// Hardwiring this logic sucks, but I don't see how else to do it.
max_secVBit_szB = max_secVBit_nodes *
(3*sizeof(Word) + VG_ROUNDUP(sizeof(SecVBitNode), sizeof(void*)));
max_shmem_szB = sizeof(primary_map) + max_SMs_szB + max_secVBit_szB;
VG_(message)(Vg_DebugMsg,
" memcheck: max sec V bit nodes: %d (%ldk, %ldM)\n",
max_secVBit_nodes, max_secVBit_szB / 1024,
max_secVBit_szB / (1024 * 1024));
VG_(message)(Vg_DebugMsg,
" memcheck: set_sec_vbits8 calls: %llu (new: %llu, updates: %llu)\n",
sec_vbits_new_nodes + sec_vbits_updates,
sec_vbits_new_nodes, sec_vbits_updates );
VG_(message)(Vg_DebugMsg,
" memcheck: max shadow mem size: %ldk, %ldM\n",
max_shmem_szB / 1024, max_shmem_szB / (1024 * 1024));
if (MC_(clo_mc_level) >= 3) {
VG_(message)(Vg_DebugMsg,
" ocacheL1: %'12lu refs %'12lu misses (%'lu lossage)\n",
stats_ocacheL1_find,
stats_ocacheL1_misses,
stats_ocacheL1_lossage );
VG_(message)(Vg_DebugMsg,
" ocacheL1: %'12lu at 0 %'12lu at 1\n",
stats_ocacheL1_find - stats_ocacheL1_misses
- stats_ocacheL1_found_at_1
- stats_ocacheL1_found_at_N,
stats_ocacheL1_found_at_1 );
VG_(message)(Vg_DebugMsg,
" ocacheL1: %'12lu at 2+ %'12lu move-fwds\n",
stats_ocacheL1_found_at_N,
stats_ocacheL1_movefwds );
VG_(message)(Vg_DebugMsg,
" ocacheL1: %'12lu sizeB %'12u useful\n",
(UWord)sizeof(OCache),
4 * OC_W32S_PER_LINE * OC_LINES_PER_SET * OC_N_SETS );
VG_(message)(Vg_DebugMsg,
" ocacheL2: %'12lu refs %'12lu misses\n",
stats__ocacheL2_refs,
stats__ocacheL2_misses );
VG_(message)(Vg_DebugMsg,
" ocacheL2: %'9lu max nodes %'9lu curr nodes\n",
stats__ocacheL2_n_nodes_max,
stats__ocacheL2_n_nodes );
VG_(message)(Vg_DebugMsg,
" niacache: %'12lu refs %'12lu misses\n",
stats__nia_cache_queries, stats__nia_cache_misses);
} else {
tl_assert(ocacheL1 == NULL);
tl_assert(ocacheL2 == NULL);
}
}
if (0) { if (0) {
VG_(message)(Vg_DebugMsg, VG_(message)(Vg_DebugMsg,
@ -6726,6 +6731,7 @@ static void mc_pre_clo_init(void)
VG_(needs_client_requests) (mc_handle_client_request); VG_(needs_client_requests) (mc_handle_client_request);
VG_(needs_sanity_checks) (mc_cheap_sanity_check, VG_(needs_sanity_checks) (mc_cheap_sanity_check,
mc_expensive_sanity_check); mc_expensive_sanity_check);
VG_(needs_print_stats) (mc_print_stats);
VG_(needs_malloc_replacement) (MC_(malloc), VG_(needs_malloc_replacement) (MC_(malloc),
MC_(__builtin_new), MC_(__builtin_new),
MC_(__builtin_vec_new), MC_(__builtin_vec_new),