ftmemsim-valgrind/include/pub_tool_libcsetjmp.h
Nicholas Nethercote 441bfc5f51 Overhaul DHAT.
This commit thoroughly overhauls DHAT, moving it out of the
"experimental" ghetto. It makes moderate changes to DHAT itself,
including dumping profiling data to a JSON format output file. It also
implements a new data viewer (as a web app, in dhat/dh_view.html).

The main benefits over the old DHAT are as follows.

- The separation of data collection and presentation means you can run a
  program once under DHAT and then sort the data in various ways. Also,
  full data is in the output file, and the viewer chooses what to omit.

- The data can be sorted in more ways than previously. Some of these
  sorts involve useful filters such as "short-lived" and "zero reads or
  zero writes".

- The tree structure view avoids the need to choose stack trace depth.
  This avoids both the problem of not enough depth (when records that
  should be distinct are combined, and may not contain enough
  information to be actionable) and the problem of too much depth (when
  records that should be combined are separated, making them seem less
  important than they really are).

- Byte and block measures are shown with a percentage relative to the
  global count, which helps gauge relative significance of different
  parts of the profile.

- Byte and blocks measures are also shown with an allocation rate
  (bytes and blocks per million instructions), which enables comparisons
  across multiple profiles, even if those profiles represent different
  workloads.

- Both global and per-node measurements are taken at the global heap
  peak ("At t-gmax"), which gives Massif-like insight into the point of
  peak memory use.

- The final/liftimes stats are a bit more useful than the old deaths
  stats. (E.g. the old deaths stats didn't take into account lifetimes
  of unfreed blocks.)

- The handling of realloc() has changed. The sequence `p = malloc(100);
  realloc(p, 200);` now increases the total block count by 2 and the
  total byte count by 300. Previously it increased them by 1 and 200.
  The new handling is a more operational view that better reflects the
  effect of allocations on performance. It makes a significant
  difference in the results, giving paths involving reallocation (e.g.
  repeated pushing to a growing vector) more prominence.

Other things of note:

- There is now testing, both regression tests that run within the
  standard test suite, and viewer-specific tests that cannot run within
  the standard test suite. The latter are run by loading
  dh_view.html?test=1 in a web browser.

- The commit puts all tool lists in Makefiles (and similar files) in the
  following consistent order: memcheck, cachegrind, callgrind, helgrind,
  drd, massif, dhat, lackey, none; exp-sgcheck, exp-bbv.

- A lot of fields in dh_main.c have been given more descriptive names.
  Those names now match those used in dh_view.js.
2019-02-01 14:54:34 +11:00

145 lines
5.2 KiB
C

/*--------------------------------------------------------------------*/
/*--- A minimal setjmp/longjmp facility. pub_tool_libcsetjmp.h ---*/
/*--------------------------------------------------------------------*/
/*
This file is part of Valgrind, a dynamic binary instrumentation
framework.
Copyright (C) 2010-2017 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_TOOL_LIBCSETJMP_H
#define __PUB_TOOL_LIBCSETJMP_H
#include "pub_tool_basics.h" // UWord
//--------------------------------------------------------------------
// PURPOSE: Provides a minimal setjmp/longjmp facility, that saves/
// restores integer registers, but not necessarily anything more.
//--------------------------------------------------------------------
/* This provides an extremely minimal setjmp/longjmp facility, in
which only the host's integer registers are saved/restored. Or at
least, that is the minimal guaranteed functionality.
Until Apr 2011 we used __builtin_setjmp and __builtin_longjmp, but
it appears that that is not always correctly implemented. See
https://bugs.kde.org/show_bug.cgi?id=259977. So this module wraps
those functions up and facilitates replacing them with our own
implementations where necessary.
*/
/* --- !!! --- EXTERNAL HEADERS start --- !!! --- */
#include <setjmp.h>
/* --- !!! --- EXTERNAL HEADERS end --- !!! --- */
/* Don't use jmp_buf, __builtin_setjmp or __builtin_longjmp directly.
They don't always work reliably. Instead use these macros, which
provide the opportunity to supply alternative implementations as
necessary.
Note that the abstraction is done with macros (ick) rather than
functions and typedefs, since wrapping __builtin_setjmp up in a
second function (eg, VG_(minimal_setjmp)) doesn't seem to work for
whatever reason -- returns via a VG_(minimal_longjmp) go wrong.
VG_MINIMAL_SETJMP stores the current integer register state in the
supplied argument, and returns zero. VG_MINIMAL_LONGJMP resumes
with the previously saved state, and returns a nonzero, word-sized
value. The caller must test all bits of the value in order to make
a zero/non-zero determination.
*/
#if defined(VGP_ppc32_linux)
#define VG_MINIMAL_JMP_BUF(_name) UInt _name [32+1+1]
__attribute__((returns_twice))
UWord VG_MINIMAL_SETJMP(VG_MINIMAL_JMP_BUF(_env));
__attribute__((noreturn))
void VG_MINIMAL_LONGJMP(VG_MINIMAL_JMP_BUF(_env));
#elif defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux)
#define VG_MINIMAL_JMP_BUF(_name) ULong _name [32+1+1]
__attribute__((returns_twice))
UWord VG_MINIMAL_SETJMP(VG_MINIMAL_JMP_BUF(_env));
__attribute__((noreturn))
void VG_MINIMAL_LONGJMP(VG_MINIMAL_JMP_BUF(_env));
#elif defined(VGP_amd64_linux) || defined(VGP_amd64_darwin) || \
defined(VGP_amd64_solaris)
#define VG_MINIMAL_JMP_BUF(_name) ULong _name [16+1]
__attribute__((returns_twice))
UWord VG_MINIMAL_SETJMP(VG_MINIMAL_JMP_BUF(_env));
__attribute__((noreturn))
void VG_MINIMAL_LONGJMP(VG_MINIMAL_JMP_BUF(_env));
#elif defined(VGP_x86_linux) || defined(VGP_x86_darwin) || \
defined(VGP_x86_solaris)
#define VG_MINIMAL_JMP_BUF(_name) UInt _name [8+1]
__attribute__((returns_twice))
__attribute__((regparm(1))) // this is critical; don't delete
UWord VG_MINIMAL_SETJMP(VG_MINIMAL_JMP_BUF(_env));
__attribute__((noreturn))
__attribute__((regparm(1))) // ditto
void VG_MINIMAL_LONGJMP(VG_MINIMAL_JMP_BUF(_env));
#elif defined(VGP_mips32_linux)
#define VG_MINIMAL_JMP_BUF(_name) ULong _name [104 / sizeof(ULong)]
__attribute__((returns_twice))
UWord VG_MINIMAL_SETJMP(VG_MINIMAL_JMP_BUF(_env));
__attribute__((noreturn))
void VG_MINIMAL_LONGJMP(VG_MINIMAL_JMP_BUF(_env));
#elif defined(VGP_mips64_linux)
#define VG_MINIMAL_JMP_BUF(_name) ULong _name [168 / sizeof(ULong)]
__attribute__((returns_twice))
UWord VG_MINIMAL_SETJMP(VG_MINIMAL_JMP_BUF(_env));
__attribute__((noreturn))
void VG_MINIMAL_LONGJMP(VG_MINIMAL_JMP_BUF(_env));
#else
/* The default implementation. */
#define VG_MINIMAL_JMP_BUF(_name) jmp_buf _name
#define VG_MINIMAL_SETJMP(_env) ((UWord)(__builtin_setjmp((_env))))
#define VG_MINIMAL_LONGJMP(_env) __builtin_longjmp((_env),1)
#endif
#endif // __PUB_TOOL_LIBCSETJMP_H
/*--------------------------------------------------------------------*/
/*--- end pub_tool_libcsetjmp.h ---*/
/*--------------------------------------------------------------------*/