|
From: <sv...@va...> - 2005-10-15 17:46:23
|
Author: njn
Date: 2005-10-15 18:46:18 +0100 (Sat, 15 Oct 2005)
New Revision: 4933
Log:
OSet-ified Cachegrind: =20
- The instrInfoTable was a VgHashTable, now it's an OSet. =20
- The CC table was a custom 3-level hash table, now it's an OSet. This
is easier to understand and there's no worrying about whether the hash
array sizes are big enough. It also has the nice property that the
results in the cachegrind.out.<pid> file are now sorted, so they're a b=
it
easier to read.
I did some testing and the performance difference appears to be negligibl=
e;
CC table and InstrInfo table lookups and traversal aren't that critical.
=20
Modified:
trunk/cachegrind/cg_main.c
Modified: trunk/cachegrind/cg_main.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/cachegrind/cg_main.c 2005-10-15 17:18:08 UTC (rev 4932)
+++ trunk/cachegrind/cg_main.c 2005-10-15 17:46:18 UTC (rev 4933)
@@ -31,7 +31,6 @@
=20
#include "pub_tool_basics.h"
#include "pub_tool_debuginfo.h"
-#include "pub_tool_hashtable.h"
#include "pub_tool_libcbase.h"
#include "pub_tool_libcassert.h"
#include "pub_tool_libcfile.h"
@@ -40,6 +39,7 @@
#include "pub_tool_machine.h"
#include "pub_tool_mallocfree.h"
#include "pub_tool_options.h"
+#include "pub_tool_oset.h"
#include "pub_tool_profile.h"
#include "pub_tool_tooliface.h"
#include "pub_tool_clientstate.h"
@@ -55,7 +55,7 @@
#define DEBUG_CG 0
=20
#define MIN_LINE_SIZE 16
-#define FILE_LEN 256
+#define FILE_LEN VKI_PATH_MAX
#define FN_LEN 256
=20
/*------------------------------------------------------------*/
@@ -84,84 +84,119 @@
//------------------------------------------------------------
// Primary data structure #1: CC table
// - Holds the per-source-line hit/miss stats, grouped by file/function/=
line.
-// - hash(file, hash(fn, hash(line+CC)))
-// - Each hash table is separately chained.
-// - The array sizes below work fairly well for Konqueror.
-// - Lookups done by instr_addr, which is converted immediately to a sou=
rce
-// location.
+// - an ordered set of CCs. CC indexing done by file/function/line (as
+// determined from the instrAddr).
// - Traversed for dumping stats at end in file/func/line hierarchy.
=20
-#define N_FILE_ENTRIES 251
-#define N_FN_ENTRIES 53
-#define N_LINE_ENTRIES 37
+typedef struct {
+ Char* file;
+ Char* fn;
+ Int line;
+}
+CodeLoc;
=20
-typedef struct _lineCC lineCC;
-struct _lineCC {
- Int line;
- CC Ir;
- CC Dr;
- CC Dw;
- lineCC* next;
+typedef struct _LineCC LineCC;
+struct _LineCC {
+ CodeLoc loc;
+ CC Ir;
+ CC Dr;
+ CC Dw;
};
=20
-typedef struct _fnCC fnCC;
-struct _fnCC {
- Char* fn;
- fnCC* next;
- lineCC* lines[N_LINE_ENTRIES];
-};
+// First compare file, then fn, then line.
+static Int cmp_CodeLoc_LineCC(void *vloc, void *vcc)
+{
+ Int res;
+ CodeLoc* a =3D (CodeLoc*)vloc;
+ CodeLoc* b =3D &(((LineCC*)vcc)->loc);
=20
-typedef struct _fileCC fileCC;
-struct _fileCC {
- Char* file;
- fileCC* next;
- fnCC* fns[N_FN_ENTRIES];
-};
+ res =3D VG_(strcmp)(a->file, b->file);
+ if (0 !=3D res)
+ return res;
=20
-// Top level of CC table. Auto-zeroed.
-static fileCC *CC_table[N_FILE_ENTRIES];
+ res =3D VG_(strcmp)(a->fn, b->fn);
+ if (0 !=3D res)
+ return res;
=20
+ return a->line - b->line;
+}
+
+static OSet* CC_table;
+
//------------------------------------------------------------
-// Primary data structure #2: Instr-info table
+// Primary data structure #2: InstrInfo table
// - Holds the cached info about each instr that is used for simulation.
-// - table(BB_start_addr, list(instr_info))
-// - For each BB, each instr_info in the list holds info about the
-// instruction (instr_len, instr_addr, etc), plus a pointer to its lin=
e
+// - table(BB_start_addr, list(InstrInfo))
+// - For each BB, each InstrInfo in the list holds info about the
+// instruction (instrLen, instrAddr, etc), plus a pointer to its line
// CC. This node is what's passed to the simulation function.
// - When BBs are discarded the relevant list(instr_details) is freed.
=20
-typedef struct _instr_info instr_info;
-struct _instr_info {
+typedef struct _InstrInfo InstrInfo;
+struct _InstrInfo {
Addr instr_addr;
UChar instr_len;
- lineCC* parent; // parent line-CC
+ LineCC* parent; // parent line-CC
};
=20
typedef struct _BB_info BB_info;
struct _BB_info {
- BB_info* next; // next field
- Addr BB_addr; // key
- Int n_instrs;
- instr_info instrs[0];
+ Addr BB_addr; // key
+ Int n_instrs;
+ InstrInfo instrs[0];
};
=20
-VgHashTable instr_info_table; // hash(Addr, BB_info)
+static OSet* instrInfoTable;
=20
//------------------------------------------------------------
+// Secondary data structure: string table
+// - holds strings, avoiding dups
+// - used for filenames and function names, each of which will be
+// pointed to by one or more CCs.
+// - it also allows equality checks just by pointer comparison, which
+// is good when printing the output file at the end.
+
+static OSet* stringTable;
+
+//------------------------------------------------------------
// Stats
static Int distinct_files =3D 0;
static Int distinct_fns =3D 0;
static Int distinct_lines =3D 0;
static Int distinct_instrs =3D 0;
=20
-static Int full_debug_BBs =3D 0;
-static Int file_line_debug_BBs =3D 0;
-static Int fn_debug_BBs =3D 0;
-static Int no_debug_BBs =3D 0;
+static Int full_debugs =3D 0;
+static Int file_line_debugs =3D 0;
+static Int fn_debugs =3D 0;
+static Int no_debugs =3D 0;
=20
static Int BB_retranslations =3D 0;
=20
/*------------------------------------------------------------*/
+/*--- String table operations ---*/
+/*------------------------------------------------------------*/
+
+static Int stringCmp( void* key, void* elem )
+{
+ return VG_(strcmp)(*(Char**)key, *(Char**)elem);
+}
+
+// Get a permanent string; either pull it out of the string table if it=
's
+// been encountered before, or dup it and put it into the string table.
+static Char* get_perm_string(Char* s)
+{
+ Char** s_ptr =3D VG_(OSet_Lookup)(stringTable, &s);
+ if (s_ptr) {
+ return *s_ptr;
+ } else {
+ Char** s_node =3D VG_(OSet_AllocNode)(stringTable, sizeof(Char*));
+ *s_node =3D VG_(strdup)(s);
+ VG_(OSet_Insert)(stringTable, s_node);
+ return *s_node;
+ }
+}
+
+/*------------------------------------------------------------*/
/*--- CC table operations ---*/
/*------------------------------------------------------------*/
=20
@@ -184,107 +219,43 @@
VG_(strcpy)(fn, "???");
}
if (found_file_line) {
- if (found_fn) full_debug_BBs++;
- else file_line_debug_BBs++;
+ if (found_fn) full_debugs++;
+ else file_line_debugs++;
} else {
- if (found_fn) fn_debug_BBs++;
- else no_debug_BBs++;
+ if (found_fn) fn_debugs++;
+ else no_debugs++;
}
}
=20
-static UInt hash(Char *s, UInt table_size)
-{
- const Int hash_constant =3D 256;
- Int hash_value =3D 0;
- for ( ; *s; s++)
- hash_value =3D (hash_constant * hash_value + *s) % table_size;
- return hash_value;
-}
-
-static __inline__=20
-fileCC* new_fileCC(Char filename[], fileCC* next)
-{
- // Using calloc() zeroes the fns[] array
- fileCC* cc =3D VG_(calloc)(1, sizeof(fileCC));
- cc->file =3D VG_(strdup)(filename);
- cc->next =3D next;
- return cc;
-}
-
-static __inline__=20
-fnCC* new_fnCC(Char fn[], fnCC* next)
-{
- // Using calloc() zeroes the lines[] array
- fnCC* cc =3D VG_(calloc)(1, sizeof(fnCC));
- cc->fn =3D VG_(strdup)(fn);
- cc->next =3D next;
- return cc;
-}
-
-static __inline__=20
-lineCC* new_lineCC(Int line, lineCC* next)
-{
- // Using calloc() zeroes the Ir/Dr/Dw CCs and the instrs[] array
- lineCC* cc =3D VG_(calloc)(1, sizeof(lineCC));
- cc->line =3D line;
- cc->next =3D next;
- return cc;
-}
-
// Do a three step traversal: by file, then fn, then line.
-// In all cases prepends new nodes to their chain. Returns a pointer to=
the
-// line node, creates a new one if necessary.
-static lineCC* get_lineCC(Addr origAddr)
+// Returns a pointer to the line CC, creates a new one if necessary.
+static LineCC* get_lineCC(Addr origAddr)
{
- fileCC *curr_fileCC;
- fnCC *curr_fnCC;
- lineCC *curr_lineCC;
Char file[FILE_LEN], fn[FN_LEN];
Int line;
- UInt file_hash, fn_hash, line_hash;
+ CodeLoc loc;
+ LineCC* lineCC;
=20
get_debug_info(origAddr, file, fn, &line);
=20
VGP_PUSHCC(VgpGetLineCC);
=20
- // level 1
- file_hash =3D hash(file, N_FILE_ENTRIES);
- curr_fileCC =3D CC_table[file_hash];
- while (NULL !=3D curr_fileCC && !VG_STREQ(file, curr_fileCC->file)) {
- curr_fileCC =3D curr_fileCC->next;
- }
- if (NULL =3D=3D curr_fileCC) {
- CC_table[file_hash] =3D curr_fileCC =3D=20
- new_fileCC(file, CC_table[file_hash]);
- distinct_files++;
- }
+ loc.file =3D file;
+ loc.fn =3D fn;
+ loc.line =3D line;
=20
- // level 2
- fn_hash =3D hash(fn, N_FN_ENTRIES);
- curr_fnCC =3D curr_fileCC->fns[fn_hash];
- while (NULL !=3D curr_fnCC && !VG_STREQ(fn, curr_fnCC->fn)) {
- curr_fnCC =3D curr_fnCC->next;
+ lineCC =3D VG_(OSet_Lookup)(CC_table, &loc);
+ if (!lineCC) {
+ // Allocate and zero a new node.
+ lineCC =3D VG_(OSet_AllocNode)(CC_table, sizeof(LineCC))=
;
+ lineCC->loc.file =3D get_perm_string(loc.file);
+ lineCC->loc.fn =3D get_perm_string(loc.fn);
+ lineCC->loc.line =3D loc.line;
+ VG_(OSet_Insert)(CC_table, lineCC);
}
- if (NULL =3D=3D curr_fnCC) {
- curr_fileCC->fns[fn_hash] =3D curr_fnCC =3D=20
- new_fnCC(fn, curr_fileCC->fns[fn_hash]);
- distinct_fns++;
- }
=20
- // level 3
- line_hash =3D line % N_LINE_ENTRIES;
- curr_lineCC =3D curr_fnCC->lines[line_hash];
- while (NULL !=3D curr_lineCC && line !=3D curr_lineCC->line) {
- curr_lineCC =3D curr_lineCC->next;
- }
- if (NULL =3D=3D curr_lineCC) {
- curr_fnCC->lines[line_hash] =3D curr_lineCC =3D=20
- new_lineCC(line, curr_fnCC->lines[line_hash]);
- distinct_lines++;
- }
-
VGP_POPCC(VgpGetLineCC);
- return curr_lineCC;
+ return lineCC;
}
=20
/*------------------------------------------------------------*/
@@ -292,7 +263,7 @@
/*------------------------------------------------------------*/
=20
static VG_REGPARM(1)
-void log_1I_0D_cache_access(instr_info* n)
+void log_1I_0D_cache_access(InstrInfo* n)
{
//VG_(printf)("1I_0D : CCaddr=3D0x%010lx, iaddr=3D0x%010lx, isize=3D=
%lu\n",
// n, n->instr_addr, n->instr_len);
@@ -304,7 +275,7 @@
}
=20
static VG_REGPARM(2)
-void log_2I_0D_cache_access(instr_info* n, instr_info* n2)
+void log_2I_0D_cache_access(InstrInfo* n, InstrInfo* n2)
{
//VG_(printf)("2I_0D : CC1addr=3D0x%010lx, i1addr=3D0x%010lx, i1size=3D=
%lu\n"
// " CC2addr=3D0x%010lx, i2addr=3D0x%010lx, i2size=3D=
%lu\n",
@@ -321,7 +292,7 @@
}
=20
static VG_REGPARM(3)
-void log_3I_0D_cache_access(instr_info* n, instr_info* n2, instr_info* n=
3)
+void log_3I_0D_cache_access(InstrInfo* n, InstrInfo* n2, InstrInfo* n3)
{
//VG_(printf)("3I_0D : CC1addr=3D0x%010lx, i1addr=3D0x%010lx, i1size=3D=
%lu\n"
// " CC2addr=3D0x%010lx, i2addr=3D0x%010lx, i2size=3D=
%lu\n"
@@ -343,7 +314,7 @@
}
=20
static VG_REGPARM(3)
-void log_1I_1Dr_cache_access(instr_info* n, Addr data_addr, Word data_si=
ze)
+void log_1I_1Dr_cache_access(InstrInfo* n, Addr data_addr, Word data_siz=
e)
{
//VG_(printf)("1I_1Dr: CCaddr=3D0x%010lx, iaddr=3D0x%010lx, isize=3D=
%lu\n"
// " daddr=3D0x%010lx, dsiz=
e=3D%lu\n",
@@ -360,7 +331,7 @@
}
=20
static VG_REGPARM(3)
-void log_1I_1Dw_cache_access(instr_info* n, Addr data_addr, Word data_si=
ze)
+void log_1I_1Dw_cache_access(InstrInfo* n, Addr data_addr, Word data_siz=
e)
{
//VG_(printf)("1I_1Dw: CCaddr=3D0x%010lx, iaddr=3D0x%010lx, isize=3D=
%lu\n"
// " daddr=3D0x%010lx, dsiz=
e=3D%lu\n",
@@ -377,7 +348,7 @@
}
=20
static VG_REGPARM(3)
-void log_0I_1Dr_cache_access(instr_info* n, Addr data_addr, Word data_si=
ze)
+void log_0I_1Dr_cache_access(InstrInfo* n, Addr data_addr, Word data_siz=
e)
{
//VG_(printf)("0I_1Dr: CCaddr=3D0x%010lx, daddr=3D0x%010lx, dsize=3D=
%lu\n",
// n, data_addr, data_size);
@@ -389,7 +360,7 @@
}
=20
static VG_REGPARM(3)
-void log_0I_1Dw_cache_access(instr_info* n, Addr data_addr, Word data_si=
ze)
+void log_0I_1Dw_cache_access(InstrInfo* n, Addr data_addr, Word data_siz=
e)
{
//VG_(printf)("0I_1Dw: CCaddr=3D0x%010lx, daddr=3D0x%010lx, dsize=3D=
%lu\n",
// n, data_addr, data_size);
@@ -465,10 +436,10 @@
Event events[N_EVENTS];
Int events_used;
=20
- /* The array of instr_info bins for the BB. */
+ /* The array of InstrInfo bins for the BB. */
BB_info* bbInfo;
=20
- /* Number instr_info bins 'used' so far. */
+ /* Number InstrInfo bins 'used' so far. */
Int bbInfo_i;
=20
/* The output BB being constructed. */
@@ -487,7 +458,7 @@
Int i, n_instrs;
IRStmt* st;
BB_info* bbInfo;
- =20
+
// Count number of original instrs in BB
n_instrs =3D 0;
for (i =3D 0; i < bbIn->stmts_used; i++) {
@@ -499,15 +470,16 @@
// If this assertion fails, there has been some screwup: some
// translations must have been discarded but Cachegrind hasn't discar=
ded
// the corresponding entries in the instr-info table.
- bbInfo =3D (BB_info*)VG_(HT_lookup)(instr_info_table, origAddr);
+ bbInfo =3D VG_(OSet_Lookup)(instrInfoTable, &origAddr);
tl_assert(NULL =3D=3D bbInfo);
=20
- // BB has never translated before (at this address, at least; could
- // have been unloaded and then reloaded elsewhere in memory).
- bbInfo =3D VG_(calloc)(1, sizeof(BB_info) + n_instrs*sizeof(instr_inf=
o));=20
- bbInfo->BB_addr =3D origAddr;
+ // BB never translated before (at this address, at least; could have
+ // been unloaded and then reloaded elsewhere in memory)
+ bbInfo =3D VG_(OSet_AllocNode)(instrInfoTable,
+ sizeof(BB_info) + n_instrs*sizeof(InstrI=
nfo));=20
+ bbInfo->BB_addr =3D origAddr;
bbInfo->n_instrs =3D n_instrs;
- VG_(HT_add_node)( instr_info_table, (VgHashNode*)bbInfo );
+ VG_(OSet_Insert)( instrInfoTable, bbInfo );
distinct_instrs++;
=20
return bbInfo;
@@ -515,7 +487,7 @@
=20
=20
static
-void init_instr_info( instr_info* n, Addr instr_addr, Int instr_len )
+void init_InstrInfo( InstrInfo* n, Addr instr_addr, Int instr_len )
{
n->instr_addr =3D instr_addr;
n->instr_len =3D instr_len;
@@ -549,11 +521,11 @@
}
}
=20
-/* Reserve instr_info for the first mention of a new insn. */
+/* Reserve InstrInfo for the first mention of a new insn. */
=20
-static instr_info* reserve_instr_info ( CgState* cgs )
+static InstrInfo* reserve_InstrInfo ( CgState* cgs )
{
- instr_info* i_node;
+ InstrInfo* i_node;
tl_assert(cgs->bbInfo_i >=3D 0);
tl_assert(cgs->bbInfo_i < cgs->bbInfo->n_instrs);
i_node =3D &cgs->bbInfo->instrs[ cgs->bbInfo_i ];
@@ -562,9 +534,9 @@
}
=20
=20
-/* Find the most recently allocated instr_info. */
+/* Find the most recently allocated InstrInfo. */
=20
-static instr_info* find_most_recent_instr_info ( CgState* cgs )
+static InstrInfo* find_most_recent_InstrInfo ( CgState* cgs )
{
tl_assert(cgs->bbInfo_i >=3D 0);
tl_assert(cgs->bbInfo_i <=3D cgs->bbInfo->n_instrs);
@@ -581,17 +553,17 @@
=20
static void flushEvents ( CgState* cgs )
{
- Int i, regparms;
- Char* helperName;
- void* helperAddr;
- IRExpr** argv;
- IRExpr* i_node_expr;
- IRExpr* i_node2_expr;
- IRExpr* i_node3_expr;
- IRDirty* di;
- instr_info* i_node;
- instr_info* i_node2;
- instr_info* i_node3;
+ Int i, regparms;
+ Char* helperName;
+ void* helperAddr;
+ IRExpr** argv;
+ IRExpr* i_node_expr;
+ IRExpr* i_node2_expr;
+ IRExpr* i_node3_expr;
+ IRDirty* di;
+ InstrInfo* i_node;
+ InstrInfo* i_node2;
+ InstrInfo* i_node3;
=20
i =3D 0;
while (i < cgs->events_used) {
@@ -609,7 +581,7 @@
showEvent( &cgs->events[i] );
}
=20
- /* For any event we find the relevant instr_info. The following
+ /* For any event we find the relevant InstrInfo. The following
assumes that Event_Ir is the first event to refer to any
specific insn, and so a new entry in the cgs->bbInfo->instrs
is allocated. All other events (Dr,Dw,Dm) must refer to the
@@ -617,16 +589,16 @@
most-recently allocated instrs[] entry, which must exist. */
=20
if (cgs->events[i].ekind =3D=3D Event_Ir) {
- /* allocate an instr_info and fill in its addr/size. */
- i_node =3D reserve_instr_info( cgs );
+ /* allocate an InstrInfo and fill in its addr/size. */
+ i_node =3D reserve_InstrInfo( cgs );
tl_assert(i_node);
- init_instr_info( i_node,
- (Addr)cgs->events[i].iaddr, /* i addr */
- cgs->events[i].size /* i size */);
+ init_InstrInfo( i_node,
+ (Addr)cgs->events[i].iaddr, /* i addr */
+ cgs->events[i].size /* i size */);
} else {
/* use the most-recently allocated i_node but don't mess with
its internals */
- i_node =3D find_most_recent_instr_info( cgs );
+ i_node =3D find_most_recent_InstrInfo( cgs );
/* it must actually exist */
tl_assert(i_node);
/* it must match the declared parent instruction of this
@@ -674,18 +646,18 @@
helperName =3D "log_3I_0D_cache_access";
helperAddr =3D &log_3I_0D_cache_access;
=20
- i_node2 =3D reserve_instr_info( cgs );
+ i_node2 =3D reserve_InstrInfo( cgs );
tl_assert(i_node2);
- init_instr_info( i_node2,
- (Addr)cgs->events[i+1].iaddr, /* i addr =
*/
- cgs->events[i+1].size /* i size */);
+ init_InstrInfo( i_node2,
+ (Addr)cgs->events[i+1].iaddr, /* i addr *=
/
+ cgs->events[i+1].size /* i size */);
i_node2_expr =3D mkIRExpr_HWord( (HWord)i_node2 );
=20
- i_node3 =3D reserve_instr_info( cgs );
+ i_node3 =3D reserve_InstrInfo( cgs );
tl_assert(i_node3);
- init_instr_info( i_node3,
- (Addr)cgs->events[i+2].iaddr, /* i addr =
*/
- cgs->events[i+2].size /* i size */);
+ init_InstrInfo( i_node3,
+ (Addr)cgs->events[i+2].iaddr, /* i addr *=
/
+ cgs->events[i+2].size /* i size */);
i_node3_expr =3D mkIRExpr_HWord( (HWord)i_node3 );
=20
argv =3D mkIRExprVec_3( i_node_expr, i_node2_expr, i_node=
3_expr );
@@ -698,11 +670,11 @@
&& cgs->events[i+1].ekind =3D=3D Event_Ir) {
helperName =3D "log_2I_0D_cache_access";
helperAddr =3D &log_2I_0D_cache_access;
- i_node2 =3D reserve_instr_info( cgs );
+ i_node2 =3D reserve_InstrInfo( cgs );
tl_assert(i_node2);
- init_instr_info( i_node2,
- (Addr)cgs->events[i+1].iaddr, /* i addr =
*/
- cgs->events[i+1].size /* i size */);
+ init_InstrInfo( i_node2,
+ (Addr)cgs->events[i+1].iaddr, /* i addr *=
/
+ cgs->events[i+1].size /* i size */);
i_node2_expr =3D mkIRExpr_HWord( (HWord)i_node2 );
argv =3D mkIRExprVec_2( i_node_expr, i_node2_expr );
regparms =3D 2;
@@ -1074,30 +1046,12 @@
=20
static Char* cachegrind_out_file;
=20
-static void fprint_lineCC(Int fd, lineCC* n)
-{
- Char buf[512];
- VG_(sprintf)(buf, "%u %llu %llu %llu %llu %llu %llu %llu %llu %llu\n"=
,
- n->line,
- n->Ir.a, n->Ir.m1, n->Ir.m2,=20
- n->Dr.a, n->Dr.m1, n->Dr.m2,
- n->Dw.a, n->Dw.m1, n->Dw.m2);
- VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
-
- Ir_total.a +=3D n->Ir.a; Ir_total.m1 +=3D n->Ir.m1; Ir_total.m2 +=3D=
n->Ir.m2;
- Dr_total.a +=3D n->Dr.a; Dr_total.m1 +=3D n->Dr.m1; Dr_total.m2 +=3D=
n->Dr.m2;
- Dw_total.a +=3D n->Dw.a; Dw_total.m1 +=3D n->Dw.m1; Dw_total.m2 +=3D=
n->Dw.m2;
-}
-
static void fprint_CC_table_and_calc_totals(void)
{
- Int fd;
+ Int i, fd;
SysRes sres;
- Char buf[512];
- fileCC *curr_fileCC;
- fnCC *curr_fnCC;
- lineCC *curr_lineCC;
- Int i, j, k;
+ Char buf[512], *currFile =3D NULL, *currFn =3D NULL;
+ LineCC* lineCC;
=20
VGP_PUSHCC(VgpCacheResults);
=20
@@ -1143,32 +1097,48 @@
VG_(sprintf)(buf, "\nevents: Ir I1mr I2mr Dr D1mr D2mr Dw D1mw D2mw\n=
");
VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
=20
- // Six loops here: three for the hash table arrays, and three for th=
e
- // chains hanging off the hash table arrays.
- for (i =3D 0; i < N_FILE_ENTRIES; i++) {
- curr_fileCC =3D CC_table[i];
- while (curr_fileCC !=3D NULL) {
- VG_(sprintf)(buf, "fl=3D%s\n", curr_fileCC->file);
+ // Traverse every lineCC
+ VG_(OSet_ResetIter)(CC_table);
+ while ( (lineCC =3D VG_(OSet_Next)(CC_table)) ) {
+ // If we've hit a new file, print a "fl=3D" line. Note that becau=
se
+ // each string is stored exactly once in the string table, we can =
use
+ // pointer comparison rather than strcmp() to test for equality, w=
hich
+ // is good because most of the time the comparisons are equal and =
so
+ // the whole strings would have to be traversed.
+ if ( lineCC->loc.file !=3D currFile ) {
+ currFile =3D lineCC->loc.file;
+ VG_(sprintf)(buf, "fl=3D%s\n", currFile);
VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
+ distinct_files++;
+ }
+ // If we've hit a new function, print a "fn=3D" line.
+ if ( lineCC->loc.fn !=3D currFn ) {
+ currFn =3D lineCC->loc.fn;
+ VG_(sprintf)(buf, "fn=3D%s\n", currFn);
+ VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
+ distinct_fns++;
+ }
=20
- for (j =3D 0; j < N_FN_ENTRIES; j++) {
- curr_fnCC =3D curr_fileCC->fns[j];
- while (curr_fnCC !=3D NULL) {
- VG_(sprintf)(buf, "fn=3D%s\n", curr_fnCC->fn);
- VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
+ // Print the LineCC
+ VG_(sprintf)(buf, "%u %llu %llu %llu %llu %llu %llu %llu %llu %llu=
\n",
+ lineCC->loc.line,
+ lineCC->Ir.a, lineCC->Ir.m1, lineCC->Ir.m2,=20
+ lineCC->Dr.a, lineCC->Dr.m1, lineCC->Dr.m2,
+ lineCC->Dw.a, lineCC->Dw.m1, lineCC->Dw.m2);
+ VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
=20
- for (k =3D 0; k < N_LINE_ENTRIES; k++) {
- curr_lineCC =3D curr_fnCC->lines[k];
- while (curr_lineCC !=3D NULL) {
- fprint_lineCC(fd, curr_lineCC);
- curr_lineCC =3D curr_lineCC->next;
- }
- }
- curr_fnCC =3D curr_fnCC->next;
- }
- }
- curr_fileCC =3D curr_fileCC->next;
- }
+ // Update summary stats
+ Ir_total.a +=3D lineCC->Ir.a;
+ Ir_total.m1 +=3D lineCC->Ir.m1;
+ Ir_total.m2 +=3D lineCC->Ir.m2;
+ Dr_total.a +=3D lineCC->Dr.a;
+ Dr_total.m1 +=3D lineCC->Dr.m1;
+ Dr_total.m2 +=3D lineCC->Dr.m2;
+ Dw_total.a +=3D lineCC->Dw.a;
+ Dw_total.m1 +=3D lineCC->Dw.m1;
+ Dw_total.m2 +=3D lineCC->Dw.m2;
+
+ distinct_lines++;
}
=20
// Summary stats must come after rest of table, since we calculate th=
em
@@ -1215,7 +1185,7 @@
=20
/* Make format string, getting width right for numbers */
VG_(sprintf)(fmt, "%%s %%,%dllu", l1);
- =20
+
VG_(message)(Vg_UserMsg, fmt, "I refs: ", Ir_total.a);
VG_(message)(Vg_UserMsg, fmt, "I1 misses: ", Ir_total.m1);
VG_(message)(Vg_UserMsg, fmt, "L2i misses: ", Ir_total.m2);
@@ -1225,7 +1195,7 @@
if (0 =3D=3D Ir_total.a) Ir_total.a =3D 1;
VG_(percentify)(Ir_total.m1, Ir_total.a, 2, l1+1, buf1);
VG_(message)(Vg_UserMsg, "I1 miss rate: %s", buf1);
- =20
+
VG_(percentify)(Ir_total.m2, Ir_total.a, 2, l1+1, buf1);
VG_(message)(Vg_UserMsg, "L2i miss rate: %s", buf1);
VG_(message)(Vg_UserMsg, "");
@@ -1235,7 +1205,7 @@
D_total.a =3D Dr_total.a + Dw_total.a;
D_total.m1 =3D Dr_total.m1 + Dw_total.m1;
D_total.m2 =3D Dr_total.m2 + Dw_total.m2;
- =20
+
/* Make format string, getting width right for numbers */
VG_(sprintf)(fmt, "%%s %%,%dllu (%%,%dllu rd + %%,%dllu wr)", l1, l2=
, l3);
=20
@@ -1247,7 +1217,7 @@
D_total.m2, Dr_total.m2, Dw_total.m2);
=20
p =3D 10;
- =20
+
if (0 =3D=3D D_total.a) D_total.a =3D 1;
if (0 =3D=3D Dr_total.a) Dr_total.a =3D 1;
if (0 =3D=3D Dw_total.a) Dw_total.a =3D 1;
@@ -1280,32 +1250,35 @@
VG_(percentify)(L2_total_mr, (Ir_total.a + Dr_total.a), 1, l2+1, buf2=
);
VG_(percentify)(L2_total_mw, Dw_total.a, 1, l3+1, buf3=
);
VG_(message)(Vg_UserMsg, "L2 miss rate: %s (%s + %s )", buf1, buf=
2,buf3);
- =20
=20
+
// Various stats
if (VG_(clo_verbosity) > 1) {
- Int BB_lookups =3D full_debug_BBs + fn_debug_BBs +
- file_line_debug_BBs + no_debug_BBs;
- =20
+ Int debug_lookups =3D full_debugs + fn_debugs +
+ file_line_debugs + no_debugs;
+
VG_(message)(Vg_DebugMsg, "");
- VG_(message)(Vg_DebugMsg, "Distinct files: %d", distinct_files)=
;
- VG_(message)(Vg_DebugMsg, "Distinct fns: %d", distinct_fns);
- VG_(message)(Vg_DebugMsg, "Distinct lines: %d", distinct_lines)=
;
- VG_(message)(Vg_DebugMsg, "Distinct instrs: %d", distinct_instrs=
);
- VG_(message)(Vg_DebugMsg, "BB lookups: %d", BB_lookups);
- VG_(message)(Vg_DebugMsg, "With full debug info:%3d%% (%d)",=
=20
- full_debug_BBs * 100 / BB_lookups,
- full_debug_BBs);
- VG_(message)(Vg_DebugMsg, "With file/line debug info:%3d%% (%d)",=
=20
- file_line_debug_BBs * 100 / BB_lookups,
- file_line_debug_BBs);
- VG_(message)(Vg_DebugMsg, "With fn name debug info:%3d%% (%d)",=
=20
- fn_debug_BBs * 100 / BB_lookups,
- fn_debug_BBs);
- VG_(message)(Vg_DebugMsg, "With no debug info:%3d%% (%d)",=
=20
- no_debug_BBs * 100 / BB_lookups,
- no_debug_BBs);
- VG_(message)(Vg_DebugMsg, "BBs Retranslated: %d", BB_retranslatio=
ns);
+ VG_(message)(Vg_DebugMsg, "cachegrind: distinct files: %d", disti=
nct_files);
+ VG_(message)(Vg_DebugMsg, "cachegrind: distinct fns: %d", disti=
nct_fns);
+ VG_(message)(Vg_DebugMsg, "cachegrind: distinct lines: %d", disti=
nct_lines);
+ VG_(message)(Vg_DebugMsg, "cachegrind: distinct instrs:%d", disti=
nct_instrs);
+ VG_(message)(Vg_DebugMsg, "cachegrind: debug lookups : %d", =
debug_lookups);
+ VG_(message)(Vg_DebugMsg, "cachegrind: with full info:%3d%% =
(%d)",=20
+ full_debugs * 100 / debug_lookups, full_debugs);
+ VG_(message)(Vg_DebugMsg, "cachegrind: with file/line info:%3d%% =
(%d)",=20
+ file_line_debugs * 100 / debug_lookups, file_line_de=
bugs);
+ VG_(message)(Vg_DebugMsg, "cachegrind: with fn name info:%3d%% =
(%d)",=20
+ fn_debugs * 100 / debug_lookups, fn_debugs);
+ VG_(message)(Vg_DebugMsg, "cachegrind: with zero info:%3d%% =
(%d)",=20
+ no_debugs * 100 / debug_lookups, no_debugs);
+ VG_(message)(Vg_DebugMsg, "cachegrind: BBs Retranslated: %d",
+ BB_retranslations);
+ VG_(message)(Vg_DebugMsg, "cachegrind: string table size: %u",
+ VG_(OSet_Size)(stringTable));
+ VG_(message)(Vg_DebugMsg, "cachegrind: CC table size: %u",
+ VG_(OSet_Size)(CC_table));
+ VG_(message)(Vg_DebugMsg, "cachegrind: InstrInfo table size: %u",
+ VG_(OSet_Size)(instrInfoTable));
}
VGP_POPCC(VgpCacheResults);
}
@@ -1319,7 +1292,7 @@
// unmapped or modified, or for any arbitrary reason.
static void cg_discard_basic_block_info ( VexGuestExtents vge )
{
- VgHashNode* bbInfo;
+ BB_info* bbInfo;
=20
tl_assert(vge.n_used > 0);
=20
@@ -1328,10 +1301,9 @@
(void*)(Addr)vge.base[0], (ULong)vge.len[0]);
=20
// Get BB info, remove from table, free BB info. Simple!
- bbInfo =3D VG_(HT_remove)(instr_info_table, (UWord)vge.base[0]);
+ bbInfo =3D VG_(OSet_Remove)(instrInfoTable, &(vge.base[0]));
tl_assert(NULL !=3D bbInfo);
-
- VG_(free)(bbInfo);
+ VG_(OSet_FreeNode)(instrInfoTable, bbInfo);
}
=20
/*--------------------------------------------------------------------*/
@@ -1449,7 +1421,15 @@
VG_(sprintf)(cachegrind_out_file, "%s/cachegrind.out.%d",
base_dir, VG_(getpid)());
=20
- instr_info_table =3D VG_(HT_construct)( 4999 ); // prime, biggish
+ CC_table =3D VG_(OSet_Create)(offsetof(LineCC, loc),
+ cmp_CodeLoc_LineCC,
+ VG_(malloc), VG_(free));
+ instrInfoTable =3D VG_(OSet_Create)(offsetof(BB_info, BB_addr),
+ NULL,
+ VG_(malloc), VG_(free));
+ stringTable =3D VG_(OSet_Create)(/*keyOff*/0,
+ stringCmp,
+ VG_(malloc), VG_(free));
}
=20
VG_DETERMINE_INTERFACE_VERSION(cg_pre_clo_init)
@@ -1457,3 +1437,4 @@
/*--------------------------------------------------------------------*/
/*--- end ---*/
/*--------------------------------------------------------------------*/
+
|