pub_core_oset.h \
pub_core_redir.h \
pub_core_replacemalloc.h\
+ pub_core_sbprofile.h \
pub_core_scheduler.h \
pub_core_seqmatch.h \
pub_core_sigframe.h \
m_options.c \
m_oset.c \
m_redir.c \
+ m_sbprofile.c \
m_seqmatch.c \
m_signals.c \
m_sparsewa.c \
#include "pub_core_libcprint.h"
#include "pub_core_libcproc.h"
#include "pub_core_libcsignal.h"
+#include "pub_core_sbprofile.h"
#include "pub_core_syscall.h" // VG_(strerror)
#include "pub_core_mach.h"
#include "pub_core_machine.h"
" --sanity-level=<number> level of sanity checking to do [1]\n"
" --trace-flags=<XXXXXXXX> show generated code? (X = 0|1) [00000000]\n"
" --profile-flags=<XXXXXXXX> ditto, but for profiling (X = 0|1) [00000000]\n"
+" --profile-interval=<number> show profile every <number> event checks\n"
+" [0, meaning only at the end of the run]\n"
" --trace-notbelow=<number> only show BBs above <number> [999999999]\n"
" --trace-notabove=<number> only show BBs below <number> [0]\n"
" --trace-syscalls=no|yes show all system calls? [no]\n"
" 0000 0100 show selecting insns\n"
" 0000 0010 show after reg-alloc\n"
" 0000 0001 show final assembly\n"
-" (Nb: you need --trace-notbelow and/or --trace-notabove with --trace-flags for full details)\n"
+" 0000 0000 show summary profile only\n"
+" (Nb: you need --trace-notbelow and/or --trace-notabove "
+" with --trace-flags for full details)\n"
"\n"
" debugging options for Valgrind tools that report errors\n"
" --dump-error=<number> show translation for basic block associated\n"
/* "stuvwxyz" --> stuvwxyz (binary) */
else if VG_STR_CLO(arg, "--trace-flags", tmp_str) {
Int j;
-
if (8 != VG_(strlen)(tmp_str)) {
VG_(fmsg_bad_option)(arg,
"--trace-flags argument must have 8 digits\n");
}
}
+ else if VG_INT_CLO (arg, "--trace-notbelow", VG_(clo_trace_notbelow)) {}
+
+ else if VG_INT_CLO (arg, "--trace-notabove", VG_(clo_trace_notabove)) {}
+
/* "stuvwxyz" --> stuvwxyz (binary) */
else if VG_STR_CLO(arg, "--profile-flags", tmp_str) {
Int j;
-
if (8 != VG_(strlen)(tmp_str)) {
VG_(fmsg_bad_option)(arg,
"--profile-flags argument must have 8 digits\n");
}
for (j = 0; j < 8; j++) {
if ('0' == tmp_str[j]) { /* do nothing */ }
- else if ('1' == tmp_str[j]) VG_(clo_profile_flags) |= (1 << (7-j));
+ else if ('1' == tmp_str[j]) VG_(clo_profyle_flags) |= (1 << (7-j));
else {
VG_(fmsg_bad_option)(arg,
"--profile-flags argument can only contain 0s and 1s\n");
}
}
+ VG_(clo_profyle_sbs) = True;
}
- else if VG_INT_CLO (arg, "--trace-notbelow", VG_(clo_trace_notbelow)) {}
-
- else if VG_INT_CLO (arg, "--trace-notabove", VG_(clo_trace_notabove)) {}
+ else if VG_INT_CLO (arg, "--profile-interval",
+ VG_(clo_profyle_interval)) {}
else if VG_XACT_CLO(arg, "--gen-suppressions=no",
VG_(clo_gen_suppressions), 0) {}
}
-/*====================================================================*/
-/*=== BB profiling ===*/
-/*====================================================================*/
-
-static
-void show_BB_profile ( BBProfEntry tops[], UInt n_tops, ULong score_total )
-{
- ULong score_cumul, score_here;
- HChar buf_cumul[10], buf_here[10];
- HChar name[64];
- Int r;
-
- VG_(printf)("\n");
- VG_(printf)("-----------------------------------------------------------\n");
- VG_(printf)("--- BEGIN BB Profile (summary of scores) ---\n");
- VG_(printf)("-----------------------------------------------------------\n");
- VG_(printf)("\n");
-
- VG_(printf)("Total score = %lld\n\n", score_total);
-
- score_cumul = 0;
- for (r = 0; r < n_tops; r++) {
- if (tops[r].addr == 0)
- continue;
- name[0] = 0;
- VG_(get_fnname_w_offset)(tops[r].addr, name, 64);
- name[63] = 0;
- score_here = tops[r].score;
- score_cumul += score_here;
- VG_(percentify)(score_cumul, score_total, 2, 6, buf_cumul);
- VG_(percentify)(score_here, score_total, 2, 6, buf_here);
- VG_(printf)("%3d: (%9lld %s) %9lld %s 0x%llx %s\n",
- r,
- score_cumul, buf_cumul,
- score_here, buf_here, tops[r].addr, name );
- }
-
- VG_(printf)("\n");
- VG_(printf)("-----------------------------------------------------------\n");
- VG_(printf)("--- BB Profile (BB details) ---\n");
- VG_(printf)("-----------------------------------------------------------\n");
- VG_(printf)("\n");
-
- score_cumul = 0;
- for (r = 0; r < n_tops; r++) {
- if (tops[r].addr == 0)
- continue;
- name[0] = 0;
- VG_(get_fnname_w_offset)(tops[r].addr, name, 64);
- name[63] = 0;
- score_here = tops[r].score;
- score_cumul += score_here;
- VG_(percentify)(score_cumul, score_total, 2, 6, buf_cumul);
- VG_(percentify)(score_here, score_total, 2, 6, buf_here);
- VG_(printf)("\n");
- VG_(printf)("=-=-=-=-=-=-=-=-=-=-=-=-=-= begin BB rank %d "
- "=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n", r);
- VG_(printf)("%3d: (%9lld %s) %9lld %s 0x%llx %s\n",
- r,
- score_cumul, buf_cumul,
- score_here, buf_here, tops[r].addr, name );
- VG_(printf)("\n");
- VG_(discard_translations)(tops[r].addr, 1, "bb profile");
- VG_(translate)(0, tops[r].addr, True, VG_(clo_profile_flags), 0, True);
- VG_(printf)("=-=-=-=-=-=-=-=-=-=-=-=-=-= end BB rank %d "
- "=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n", r);
- }
-
- VG_(printf)("\n");
- VG_(printf)("-----------------------------------------------------------\n");
- VG_(printf)("--- END BB Profile ---\n");
- VG_(printf)("-----------------------------------------------------------\n");
- VG_(printf)("\n");
-}
-
-
/*====================================================================*/
/*=== main() ===*/
/*====================================================================*/
VG_(print_arena_cc_analysis)();
}
- if (VG_(clo_profile_flags) > 0) {
- #define N_MAX 200
- BBProfEntry tops[N_MAX];
- ULong score_total = VG_(get_BB_profile) (tops, N_MAX);
- show_BB_profile(tops, N_MAX, score_total);
+ /* If profiling has been requested, but with zero interval, it
+ means "profile at the end of the run only". In which case we
+ need to dump the profile now. */
+ if (VG_(clo_profyle_sbs) && VG_(clo_profyle_interval) == 0) {
+ VG_(get_and_show_SB_profile)(0/*denoting end-of-run*/);
}
/* Print Vex storage stats */
/* Flush any output cached by previous calls to VG_(message). */
VG_(message_flush)();
- /* terminate gdbserver if ever it was started. We terminate it here so that it get
- the output above if output was redirected to gdb */
+ /* terminate gdbserver if ever it was started. We terminate it here
+ so that it get the output above if output was redirected to
+ gdb */
VG_(gdbserver_exit) (tid, tids_schedretcode);
/* Ok, finally exit in the os-specific way, according to the scheduler's
const HChar* VG_(clo_fullpath_after)[VG_CLO_MAX_FULLPATH_AFTER];
const HChar* VG_(clo_extra_debuginfo_path) = NULL;
UChar VG_(clo_trace_flags) = 0; // 00000000b
-UChar VG_(clo_profile_flags) = 0; // 00000000b
+Bool VG_(clo_profyle_sbs) = False;
+UChar VG_(clo_profyle_flags) = 0; // 00000000b
+ULong VG_(clo_profyle_interval) = 0;
Int VG_(clo_trace_notbelow) = -1; // unspecified
Int VG_(clo_trace_notabove) = -1; // unspecified
Bool VG_(clo_trace_syscalls) = False;
--- /dev/null
+
+/*--------------------------------------------------------------------*/
+/*--- For printing superblock profiles m_sbprofile.c ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+ This file is part of Valgrind, a dynamic binary instrumentation
+ framework.
+
+ Copyright (C) 2012-2012 Mozilla Foundation
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307, USA.
+
+ The GNU General Public License is contained in the file COPYING.
+*/
+
+/* Contributed by Julian Seward <jseward@acm.org> */
+
+#include "pub_core_basics.h"
+#include "pub_core_transtab.h"
+#include "pub_core_libcbase.h"
+#include "pub_core_libcprint.h"
+#include "pub_core_libcassert.h"
+#include "pub_core_debuginfo.h"
+#include "pub_core_translate.h"
+#include "pub_core_options.h"
+#include "pub_core_sbprofile.h" // self
+
+/*====================================================================*/
+/*=== SB profiling ===*/
+/*====================================================================*/
+
+static UInt n_profiles = 0;
+
+static
+void show_SB_profile ( SBProfEntry tops[], UInt n_tops,
+ ULong score_total, ULong ecs_done )
+{
+ ULong score_cumul, score_cumul_saved, score_here;
+ HChar buf_cumul[10], buf_here[10];
+ HChar name[64];
+ Int r; /* must be signed */
+
+ HChar ecs_txt[50];
+ if (ecs_done > 0) {
+ VG_(sprintf)(ecs_txt, "%'llu ecs done", ecs_done);
+ } else {
+ VG_(strcpy)(ecs_txt, "for the entire run");
+ }
+
+ vg_assert(VG_(clo_profyle_sbs));
+
+ VG_(printf)("\n");
+ VG_(printf)("<<<---<<<---<<<---<<<---<<<---<<<---<<<---"
+ "<<<---<<<---<<<---<<<---<<<---<<<\n");
+ VG_(printf)("<<<---<<<---<<<---<<<---<<<---<<<---<<<---"
+ "<<<---<<<---<<<---<<<---<<<---<<<\n");
+ VG_(printf)("\n");
+ VG_(printf)("<<< BEGIN SB Profile #%u (%s)\n",
+ ++n_profiles, ecs_txt);
+ VG_(printf)("<<<\n");
+ VG_(printf)("\n");
+
+ VG_(printf)("Total score = %'lld\n\n", score_total);
+
+ /* Print an initial per-block summary. */
+ VG_(printf)("rank ---cumulative--- -----self-----\n");
+ score_cumul = 0;
+ for (r = 0; r < n_tops; r++) {
+ if (tops[r].addr == 0)
+ continue;
+ if (tops[r].score == 0)
+ continue;
+ name[0] = 0;
+ VG_(get_fnname_w_offset)(tops[r].addr, name, 64);
+ name[63] = 0;
+ score_here = tops[r].score;
+ score_cumul += score_here;
+ VG_(percentify)(score_cumul, score_total, 2, 6, buf_cumul);
+ VG_(percentify)(score_here, score_total, 2, 6, buf_here);
+ VG_(printf)("%3d: (%9lld %s) %9lld %s 0x%llx %s\n",
+ r,
+ score_cumul, buf_cumul,
+ score_here, buf_here, tops[r].addr, name );
+ }
+ score_cumul_saved = score_cumul;
+
+ if (VG_(clo_profyle_flags) > 0) {
+
+ /* Show the details, if requested. */
+ VG_(printf)("\n");
+ VG_(printf)("-----------------------------"
+ "------------------------------\n");
+ VG_(printf)("--- SB Profile (SB details) "
+ " ---\n");
+ VG_(printf)("-----------------------------"
+ "------------------------------\n");
+ VG_(printf)("\n");
+
+ score_cumul = 0;
+ for (r = 0; r < n_tops; r++) {
+ if (tops[r].addr == 0)
+ continue;
+ if (tops[r].score == 0)
+ continue;
+ name[0] = 0;
+ VG_(get_fnname_w_offset)(tops[r].addr, name, 64);
+ name[63] = 0;
+ score_here = tops[r].score;
+ score_cumul += score_here;
+ VG_(percentify)(score_cumul, score_total, 2, 6, buf_cumul);
+ VG_(percentify)(score_here, score_total, 2, 6, buf_here);
+ VG_(printf)("\n");
+ VG_(printf)("=-=-=-=-=-=-=-=-=-=-=-=-=-= begin SB rank %d "
+ "=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n", r);
+ VG_(printf)("%3d: (%9lld %s) %9lld %s 0x%llx %s\n",
+ r,
+ score_cumul, buf_cumul,
+ score_here, buf_here, tops[r].addr, name );
+ VG_(printf)("\n");
+ VG_(discard_translations)(tops[r].addr, 1, "bb profile");
+ VG_(translate)(0, tops[r].addr, True, VG_(clo_profyle_flags), 0, True);
+ VG_(printf)("=-=-=-=-=-=-=-=-=-=-=-=-=-= end SB rank %d "
+ "=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n", r);
+ }
+
+ /* Print a final per-block summary, in reverse order, for the
+ convenience of people reading up from the end. */
+ score_cumul = score_cumul_saved;
+ for (r = n_tops-1; r >= 0; r--) {
+ if (tops[r].addr == 0)
+ continue;
+ if (tops[r].score == 0)
+ continue;
+ name[0] = 0;
+ VG_(get_fnname_w_offset)(tops[r].addr, name, 64);
+ name[63] = 0;
+ score_here = tops[r].score;
+ VG_(percentify)(score_cumul, score_total, 2, 6, buf_cumul);
+ VG_(percentify)(score_here, score_total, 2, 6, buf_here);
+ VG_(printf)("%3d: (%9lld %s) %9lld %s 0x%llx %s\n",
+ r,
+ score_cumul, buf_cumul,
+ score_here, buf_here, tops[r].addr, name );
+ score_cumul -= score_here;
+ }
+ VG_(printf)("rank ---cumulative--- -----self-----\n");
+
+ }
+
+ VG_(printf)("\n");
+ VG_(printf)(">>>\n");
+ VG_(printf)(">>> END SB Profile #%u (%s)\n",
+ n_profiles, ecs_txt);
+ VG_(printf)(">>>\n");
+ VG_(printf)(">>>--->>>--->>>--->>>--->>>--->>>--->>>---"
+ ">>>--->>>--->>>--->>>--->>>--->>>\n");
+ VG_(printf)(">>>--->>>--->>>--->>>--->>>--->>>--->>>---"
+ ">>>--->>>--->>>--->>>--->>>--->>>\n");
+ VG_(printf)("\n");
+}
+
+
+/* Get and print a profile. Also, zero out the counters so that if we
+ call it again later, the second call will only show new work done
+ since the first call. ecs_done == 0 is taken to mean this is a
+ run-end profile. */
+void VG_(get_and_show_SB_profile) ( ULong ecs_done )
+{
+ /* The number of blocks to show for a end-of-run profile */
+# define N_MAX_END 200
+ /* The number of blocks to show for a mid-run profile. */
+# define N_MAX_INTERVAL 20
+ vg_assert(N_MAX_INTERVAL <= N_MAX_END);
+ SBProfEntry tops[N_MAX_END];
+ Int nToShow = ecs_done == 0 ? N_MAX_END : N_MAX_INTERVAL;
+ ULong score_total = VG_(get_SB_profile)(tops, nToShow);
+ show_SB_profile(tops, nToShow, score_total, ecs_done);
+# undef N_MAX_END
+# undef N_MAX_INTERVAL
+}
+
+
+/*--------------------------------------------------------------------*/
+/*--- end m_sbprofile.c ---*/
+/*--------------------------------------------------------------------*/
#include "pub_core_mallocfree.h"
#include "pub_core_options.h"
#include "pub_core_replacemalloc.h"
+#include "pub_core_sbprofile.h"
#include "pub_core_signals.h"
#include "pub_core_stacks.h"
#include "pub_core_stacktrace.h" // For VG_(get_and_pp_StackTrace)()
VG_(message)(Vg_DebugMsg, " SCHED[%d]: %s\n", tid, what );
}
-/* For showing SB counts, if the user asks to see them. */
-#define SHOW_SBCOUNT_EVERY (20ULL * 1000 * 1000)
-static ULong bbs_done_lastcheck = 0;
-
+/* For showing SB profiles, if the user asks to see them. */
static
-void maybe_show_sb_counts ( void )
+void maybe_show_sb_profile ( void )
{
- Long delta = bbs_done - bbs_done_lastcheck;
+ /* DO NOT MAKE NON-STATIC */
+ static ULong bbs_done_lastcheck = 0;
+ /* */
+ vg_assert(VG_(clo_profyle_interval) > 0);
+ Long delta = (Long)(bbs_done - bbs_done_lastcheck);
vg_assert(delta >= 0);
- if (UNLIKELY(delta >= SHOW_SBCOUNT_EVERY)) {
- VG_(umsg)("%'lld superblocks executed\n", bbs_done);
+ if ((ULong)delta >= VG_(clo_profyle_interval)) {
bbs_done_lastcheck = bbs_done;
+ VG_(get_and_show_SB_profile)(bbs_done);
}
}
} /* switch (trc) */
- if (0)
- maybe_show_sb_counts();
+ if (UNLIKELY(VG_(clo_profyle_sbs)) && VG_(clo_profyle_interval) > 0)
+ maybe_show_sb_profile();
}
if (VG_(clo_trace_sched))
vta.preamble_function = preamble_fn;
vta.traceflags = verbosity;
vta.sigill_diag = VG_(clo_sigill_diag);
- vta.addProfInc = VG_(clo_profile_flags) > 0
- && kind != T_NoRedir;
+ vta.addProfInc = VG_(clo_profyle_sbs) && kind != T_NoRedir;
/* Set up the dispatch continuation-point info. If this is a
no-redir translation then it cannot be chained, and the chain-me
return ((ULong)tte->weight) * ((ULong)tte->count);
}
-ULong VG_(get_BB_profile) ( BBProfEntry tops[], UInt n_tops )
+ULong VG_(get_SB_profile) ( SBProfEntry tops[], UInt n_tops )
{
Int sno, i, r, s;
ULong score_total;
}
}
+ /* Now zero out all the counter fields, so that we can make
+ multiple calls here and just get the values since the last call,
+ each time, rather than values accumulated for the whole run. */
+ for (sno = 0; sno < N_SECTORS; sno++) {
+ if (sectors[sno].tc == NULL)
+ continue;
+ for (i = 0; i < N_TTES_PER_SECTOR; i++) {
+ if (sectors[sno].tt[i].status != InUse)
+ continue;
+ sectors[sno].tt[i].count = 0;
+ }
+ }
+
return score_total;
}
/* DEBUG: print generated code? default: 00000000 ( == NO ) */
extern UChar VG_(clo_trace_flags);
-/* DEBUG: do bb profiling? default: 00000000 ( == NO ) */
-extern UChar VG_(clo_profile_flags);
+
+/* DEBUG: do SB profiling? default: False (== NO). NOTE: does not
+ have an associated command line flag. Is set to True whenever
+ --profile-flags= is specified. */
+extern Bool VG_(clo_profyle_sbs);
+/* DEBUG: if doing SB profiling, provides bits for which JIT stages
+ are shown. Same meaning as for clo_trace_flags. default: zero (==
+ show block counts only) */
+extern UChar VG_(clo_profyle_flags);
+/* DEBUG: if doing SB profiling, dump blocks and zero counters after
+ this-many back edges (event checks). default: zero (== show
+ profiling results only at the end of the run. */
+extern ULong VG_(clo_profyle_interval);
+
/* DEBUG: if tracing codegen, be quiet until after this bb */
extern Int VG_(clo_trace_notbelow);
/* DEBUG: if tracing codegen, be quiet after this bb */
--- /dev/null
+
+/*--------------------------------------------------------------------*/
+/*--- For printing superblock profiles pub_core_sbprofile.h ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+ This file is part of Valgrind, a dynamic binary instrumentation
+ framework.
+
+ Copyright (C) 2012-2012 Mozilla Foundation
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307, USA.
+
+ The GNU General Public License is contained in the file COPYING.
+*/
+
+/* Contributed by Julian Seward <jseward@acm.org> */
+
+#ifndef __PUB_CORE_SBPROFILE_H
+#define __PUB_CORE_SBPROFILE_H
+
+/* Get and print a profile. Also, zero out the counters so that if we
+ call it again later, the second call will only show new work done
+ since the first call. ecs_done == 0 is taken to mean this is a
+ run-end profile. */
+void VG_(get_and_show_SB_profile) ( ULong ecs_done );
+
+#endif // __PUB_CORE_SBPROFILE_H
+
+/*--------------------------------------------------------------------*/
+/*--- end pub_core_sbprofile.h ---*/
+/*--------------------------------------------------------------------*/
Bool VG_(search_unredir_transtab) ( /*OUT*/AddrH* result,
Addr64 guest_addr );
-// BB profiling stuff
+// SB profiling stuff
-typedef struct _BBProfEntry {
+typedef struct _SBProfEntry {
Addr64 addr;
ULong score;
-} BBProfEntry;
+} SBProfEntry;
-extern ULong VG_(get_BB_profile) ( BBProfEntry tops[], UInt n_tops );
+extern ULong VG_(get_SB_profile) ( SBProfEntry tops[], UInt n_tops );
#endif // __PUB_CORE_TRANSTAB_H
--sanity-level=<number> level of sanity checking to do [1]
--trace-flags=<XXXXXXXX> show generated code? (X = 0|1) [00000000]
--profile-flags=<XXXXXXXX> ditto, but for profiling (X = 0|1) [00000000]
+ --profile-interval=<number> show profile every <number> event checks
+ [0, meaning only at the end of the run]
--trace-notbelow=<number> only show BBs above <number> [999999999]
--trace-notabove=<number> only show BBs below <number> [0]
--trace-syscalls=no|yes show all system calls? [no]
0000 0100 show selecting insns
0000 0010 show after reg-alloc
0000 0001 show final assembly
- (Nb: you need --trace-notbelow and/or --trace-notabove with --trace-flags for full details)
+ 0000 0000 show summary profile only
+ (Nb: you need --trace-notbelow and/or --trace-notabove with --trace-flags for full details)
debugging options for Valgrind tools that report errors
--dump-error=<number> show translation for basic block associated