1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/tools/trace-malloc/tmreader.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,191 @@ 1.4 +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- 1.5 + * 1.6 + * This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 +#ifndef tmreader_h___ 1.10 +#define tmreader_h___ 1.11 + 1.12 +#include "plhash.h" 1.13 +#include "nsTraceMalloc.h" 1.14 +#include "plarena.h" 1.15 + 1.16 +#ifdef __cplusplus 1.17 +extern "C" { 1.18 +#endif 1.19 + 1.20 +typedef struct tmreader tmreader; 1.21 +typedef struct tmevent tmevent; 1.22 +typedef struct tmcounts tmcounts; 1.23 +typedef struct tmallcounts tmallcounts; 1.24 +typedef struct tmgraphlink tmgraphlink; 1.25 +typedef struct tmgraphedge tmgraphedge; 1.26 +typedef struct tmgraphnode tmgraphnode; 1.27 +typedef struct tmcallsite tmcallsite; 1.28 +typedef struct tmmethodnode tmmethodnode; 1.29 + 1.30 +struct tmevent { 1.31 + char type; 1.32 + uint32_t serial; 1.33 + union { 1.34 + char *libname; 1.35 + char *srcname; 1.36 + struct { 1.37 + uint32_t library; 1.38 + uint32_t filename; 1.39 + uint32_t linenumber; 1.40 + char *name; 1.41 + } method; 1.42 + struct { 1.43 + uint32_t parent; 1.44 + uint32_t method; 1.45 + uint32_t offset; 1.46 + } site; 1.47 + struct { 1.48 + uint32_t interval; /* in ticks */ 1.49 + uint32_t ptr; 1.50 + uint32_t size; 1.51 + uint32_t oldserial; 1.52 + uint32_t oldptr; 1.53 + uint32_t oldsize; 1.54 + uint32_t cost; /* in ticks */ 1.55 + } alloc; 1.56 + struct { 1.57 + nsTMStats tmstats; 1.58 + uint32_t calltree_maxkids_parent; 1.59 + uint32_t calltree_maxstack_top; 1.60 + } stats; 1.61 + } u; 1.62 +}; 1.63 + 1.64 +struct tmcounts { 1.65 + uint32_t direct; /* things allocated by this node's code */ 1.66 + uint32_t total; /* direct + things from all descendents */ 1.67 +}; 1.68 + 1.69 +struct tmallcounts { 1.70 + tmcounts bytes; 1.71 + tmcounts calls; 1.72 +}; 1.73 + 1.74 +struct tmgraphnode { 1.75 + PLHashEntry entry; /* key is serial or name, value must be name */ 1.76 + tmgraphlink *in; 1.77 + tmgraphlink *out; 1.78 + tmgraphnode *up; /* parent in supergraph, e.g., JS for JS_*() */ 1.79 + tmgraphnode *down; /* subgraph kids, declining bytes.total order */ 1.80 + tmgraphnode *next; /* next kid in supergraph node's down list */ 1.81 + int low; /* 0 or lowest current tree walk level */ 1.82 + tmallcounts allocs; 1.83 + tmallcounts frees; 1.84 + double sqsum; /* sum of squared bytes.direct */ 1.85 + int sort; /* sorted index in node table, -1 if no table */ 1.86 +}; 1.87 + 1.88 +struct tmmethodnode { 1.89 + tmgraphnode graphnode; 1.90 + char *sourcefile; 1.91 + uint32_t linenumber; 1.92 +}; 1.93 + 1.94 +#define tmgraphnode_name(node) ((char*) (node)->entry.value) 1.95 +#define tmmethodnode_name(node) ((char*) (node)->graphnode.entry.value) 1.96 + 1.97 +#define tmlibrary_serial(lib) ((uint32_t) (lib)->entry.key) 1.98 +#define tmcomponent_name(comp) ((const char*) (comp)->entry.key) 1.99 +#define filename_name(hashentry) ((char*)hashentry->value) 1.100 + 1.101 +/* Half a graphedge, not including per-edge allocation stats. */ 1.102 +struct tmgraphlink { 1.103 + tmgraphlink *next; /* next fanning out from or into a node */ 1.104 + tmgraphnode *node; /* the other node (to if OUT, from if IN) */ 1.105 +}; 1.106 + 1.107 +/* 1.108 + * It's safe to downcast a "from" tmgraphlink (one linked from a node's out 1.109 + * pointer) to tmgraphedge. To go from an "out" (linked via tmgraphedge.from) 1.110 + * or "in" (linked via tmgraphedge.to) list link to its containing edge, use 1.111 + * TM_LINK_TO_EDGE(link, which). 1.112 + */ 1.113 +struct tmgraphedge { 1.114 + tmgraphlink links[2]; 1.115 + tmallcounts allocs; 1.116 + tmallcounts frees; 1.117 +}; 1.118 + 1.119 +/* Indices into tmgraphedge.links -- out must come first. */ 1.120 +#define TM_EDGE_OUT_LINK 0 1.121 +#define TM_EDGE_IN_LINK 1 1.122 + 1.123 +#define TM_LINK_TO_EDGE(link,which) ((tmgraphedge*) &(link)[-(which)]) 1.124 + 1.125 +struct tmcallsite { 1.126 + PLHashEntry entry; /* key is site serial number */ 1.127 + tmcallsite *parent; /* calling site */ 1.128 + tmcallsite *siblings; /* other sites reached from parent */ 1.129 + tmcallsite *kids; /* sites reached from here */ 1.130 + tmmethodnode *method; /* method node in tmr->methods graph */ 1.131 + uint32_t offset; /* pc offset from start of method */ 1.132 + tmallcounts allocs; 1.133 + tmallcounts frees; 1.134 + void *data; /* tmreader clients can stick arbitrary 1.135 + * data onto a callsite. 1.136 + */ 1.137 +}; 1.138 + 1.139 +struct tmreader { 1.140 + const char *program; 1.141 + void *data; 1.142 + PLHashTable *libraries; 1.143 + PLHashTable *filenames; 1.144 + PLHashTable *components; 1.145 + PLHashTable *methods; 1.146 + PLHashTable *callsites; 1.147 + PLArenaPool arena; 1.148 + tmcallsite calltree_root; 1.149 + uint32_t ticksPerSec; 1.150 +}; 1.151 + 1.152 +typedef void (*tmeventhandler)(tmreader *tmr, tmevent *event); 1.153 + 1.154 +/* The tmreader constructor and destructor. */ 1.155 +extern tmreader *tmreader_new(const char *program, void *data); 1.156 +extern void tmreader_destroy(tmreader *tmr); 1.157 + 1.158 +/* 1.159 + * Return -1 on permanent fatal error, 0 if filename can't be opened or is not 1.160 + * a trace-malloc logfile, and 1 on success. 1.161 + */ 1.162 +extern int tmreader_eventloop(tmreader *tmr, const char *filename, 1.163 + tmeventhandler eventhandler); 1.164 + 1.165 +/* Map serial number or name to graphnode or callsite. */ 1.166 +extern tmgraphnode *tmreader_library(tmreader *tmr, uint32_t serial); 1.167 +extern tmgraphnode *tmreader_filename(tmreader *tmr, uint32_t serial); 1.168 +extern tmgraphnode *tmreader_component(tmreader *tmr, const char *name); 1.169 +extern tmmethodnode *tmreader_method(tmreader *tmr, uint32_t serial); 1.170 +extern tmcallsite *tmreader_callsite(tmreader *tmr, uint32_t serial); 1.171 + 1.172 +/* 1.173 + * Connect node 'from' to node 'to' with an edge, if there isn't one already 1.174 + * connecting the nodes. Add site's allocation stats to the edge only if we 1.175 + * create the edge, or if we find that it exists, but that to->low is zero or 1.176 + * less than from->low. 1.177 + * 1.178 + * If the callsite tree already totals allocation costs (tmcounts.total for 1.179 + * each site includes tmcounts.direct for that site, plus tmcounts.total for 1.180 + * all kid sites), then the node->low watermarks should be set from the tree 1.181 + * level when walking the callsite tree, and should be set to non-zero values 1.182 + * only if zero (the root is at level 0). A low watermark should be cleared 1.183 + * when the tree walk unwinds past the level at which it was set non-zero. 1.184 + * 1.185 + * Return 0 on error (malloc failure) and 1 on success. 1.186 + */ 1.187 +extern int tmgraphnode_connect(tmgraphnode *from, tmgraphnode *to, 1.188 + tmcallsite *site); 1.189 + 1.190 +#ifdef __cplusplus 1.191 +} 1.192 +#endif 1.193 + 1.194 +#endif /* tmreader_h___ */