зеркало из https://github.com/mozilla/pjs.git
reformat these files with 'indent' so that they are actually maintainable
not part of default build
This commit is contained in:
Родитель
69be1db6c4
Коммит
d25cbadc23
|
@ -69,16 +69,18 @@
|
|||
**
|
||||
** Add a rule into the list of rules maintainted in global
|
||||
*/
|
||||
int AddRule(STGlobals *g, STCategoryRule *rule)
|
||||
int
|
||||
AddRule(STGlobals * g, STCategoryRule * rule)
|
||||
{
|
||||
if (g->mNRules % ST_ALLOC_STEP == 0)
|
||||
{
|
||||
if (g->mNRules % ST_ALLOC_STEP == 0) {
|
||||
/* Need more space */
|
||||
STCategoryRule** newrules;
|
||||
STCategoryRule **newrules;
|
||||
|
||||
newrules = (STCategoryRule **) realloc(g->mCategoryRules,
|
||||
(g->mNRules + ST_ALLOC_STEP)*sizeof(STCategoryRule *));
|
||||
if (!newrules)
|
||||
{
|
||||
(g->mNRules +
|
||||
ST_ALLOC_STEP) *
|
||||
sizeof(STCategoryRule *));
|
||||
if (!newrules) {
|
||||
REPORT_ERROR(__LINE__, AddRule_No_Memory);
|
||||
return -1;
|
||||
}
|
||||
|
@ -93,16 +95,18 @@ int AddRule(STGlobals *g, STCategoryRule *rule)
|
|||
**
|
||||
** Add the node as a child of the parent node
|
||||
*/
|
||||
int AddChild(STCategoryNode* parent, STCategoryNode* child)
|
||||
int
|
||||
AddChild(STCategoryNode * parent, STCategoryNode * child)
|
||||
{
|
||||
if (parent->nchildren % ST_ALLOC_STEP == 0)
|
||||
{
|
||||
if (parent->nchildren % ST_ALLOC_STEP == 0) {
|
||||
/* need more space */
|
||||
STCategoryNode** newnodes;
|
||||
STCategoryNode **newnodes;
|
||||
|
||||
newnodes = (STCategoryNode **) realloc(parent->children,
|
||||
(parent->nchildren + ST_ALLOC_STEP)*sizeof(STCategoryNode *));
|
||||
if (!newnodes)
|
||||
{
|
||||
(parent->nchildren +
|
||||
ST_ALLOC_STEP) *
|
||||
sizeof(STCategoryNode *));
|
||||
if (!newnodes) {
|
||||
REPORT_ERROR(__LINE__, AddChild_No_Memory);
|
||||
return -1;
|
||||
}
|
||||
|
@ -112,23 +116,24 @@ int AddChild(STCategoryNode* parent, STCategoryNode* child)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int ReParent(STCategoryNode* parent, STCategoryNode* child)
|
||||
int
|
||||
ReParent(STCategoryNode * parent, STCategoryNode * child)
|
||||
{
|
||||
PRUint32 i;
|
||||
|
||||
if (child->parent == parent)
|
||||
return 0;
|
||||
|
||||
/* Remove child from old parent */
|
||||
if (child->parent)
|
||||
{
|
||||
for (i = 0; i < child->parent->nchildren; i++)
|
||||
{
|
||||
if (child->parent->children[i] == child)
|
||||
{
|
||||
if (child->parent) {
|
||||
for (i = 0; i < child->parent->nchildren; i++) {
|
||||
if (child->parent->children[i] == child) {
|
||||
/* Remove child from list */
|
||||
if (i+1 < child->parent->nchildren)
|
||||
memmove(&child->parent->children[i], &child->parent->children[i+1],
|
||||
(child->parent->nchildren - i - 1) * sizeof(STCategoryNode*));
|
||||
if (i + 1 < child->parent->nchildren)
|
||||
memmove(&child->parent->children[i],
|
||||
&child->parent->children[i + 1],
|
||||
(child->parent->nchildren - i -
|
||||
1) * sizeof(STCategoryNode *));
|
||||
child->parent->nchildren--;
|
||||
break;
|
||||
}
|
||||
|
@ -146,11 +151,12 @@ int ReParent(STCategoryNode* parent, STCategoryNode* child)
|
|||
**
|
||||
** Given a category name, finds the Node corresponding to the category
|
||||
*/
|
||||
STCategoryNode* findCategoryNode(const char *catName, STGlobals *g)
|
||||
STCategoryNode *
|
||||
findCategoryNode(const char *catName, STGlobals * g)
|
||||
{
|
||||
PRUint32 i;
|
||||
for(i = 0; i < g->mNCategoryMap; i++)
|
||||
{
|
||||
|
||||
for (i = 0; i < g->mNCategoryMap; i++) {
|
||||
if (!strcmp(g->mCategoryMap[i]->categoryName, catName))
|
||||
return g->mCategoryMap[i]->node;
|
||||
}
|
||||
|
@ -167,24 +173,26 @@ STCategoryNode* findCategoryNode(const char *catName, STGlobals *g)
|
|||
**
|
||||
** Adds a mapping between a category and its Node into the categoryMap
|
||||
*/
|
||||
int AddCategoryNode(STCategoryNode* node, STGlobals* g)
|
||||
int
|
||||
AddCategoryNode(STCategoryNode * node, STGlobals * g)
|
||||
{
|
||||
if (g->mNCategoryMap % ST_ALLOC_STEP == 0)
|
||||
{
|
||||
if (g->mNCategoryMap % ST_ALLOC_STEP == 0) {
|
||||
/* Need more space */
|
||||
STCategoryMapEntry **newmap = (STCategoryMapEntry **) realloc(g->mCategoryMap,
|
||||
(g->mNCategoryMap + ST_ALLOC_STEP) * sizeof(STCategoryMapEntry *));
|
||||
if (!newmap)
|
||||
{
|
||||
STCategoryMapEntry **newmap =
|
||||
(STCategoryMapEntry **) realloc(g->mCategoryMap,
|
||||
(g->mNCategoryMap +
|
||||
ST_ALLOC_STEP) *
|
||||
sizeof(STCategoryMapEntry *));
|
||||
if (!newmap) {
|
||||
REPORT_ERROR(__LINE__, AddCategoryNode_No_Memory);
|
||||
return -1;
|
||||
}
|
||||
g->mCategoryMap = newmap;
|
||||
|
||||
}
|
||||
g->mCategoryMap[g->mNCategoryMap] = (STCategoryMapEntry *) calloc(1, sizeof(STCategoryMapEntry));
|
||||
if (!g->mCategoryMap[g->mNCategoryMap])
|
||||
{
|
||||
g->mCategoryMap[g->mNCategoryMap] =
|
||||
(STCategoryMapEntry *) calloc(1, sizeof(STCategoryMapEntry));
|
||||
if (!g->mCategoryMap[g->mNCategoryMap]) {
|
||||
REPORT_ERROR(__LINE__, AddCategoryNode_No_Memory);
|
||||
return -1;
|
||||
}
|
||||
|
@ -200,17 +208,18 @@ int AddCategoryNode(STCategoryNode* node, STGlobals* g)
|
|||
** Creates a new category node for category name 'catname' and makes
|
||||
** 'parent' its parent.
|
||||
*/
|
||||
STCategoryNode* NewCategoryNode(const char* catName, STCategoryNode* parent, STGlobals* g)
|
||||
STCategoryNode *
|
||||
NewCategoryNode(const char *catName, STCategoryNode * parent, STGlobals * g)
|
||||
{
|
||||
STCategoryNode* node;
|
||||
STCategoryNode *node;
|
||||
|
||||
node = (STCategoryNode *) calloc(1, sizeof(STCategoryNode));
|
||||
if (!node)
|
||||
return NULL;
|
||||
|
||||
node->runs = (STRun**)calloc(g->mCommandLineOptions.mContexts, sizeof(STRun*));
|
||||
if(NULL == node->runs)
|
||||
{
|
||||
node->runs =
|
||||
(STRun **) calloc(g->mCommandLineOptions.mContexts, sizeof(STRun *));
|
||||
if (NULL == node->runs) {
|
||||
free(node);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -235,10 +244,12 @@ STCategoryNode* NewCategoryNode(const char* catName, STCategoryNode* parent, STG
|
|||
** Add this into the tree as a leaf node. It doesnt know who its parent is. For now we make
|
||||
** root as its parent
|
||||
*/
|
||||
int ProcessCategoryLeafRule(STCategoryRule* leafRule, STCategoryNode *root, STGlobals *g)
|
||||
int
|
||||
ProcessCategoryLeafRule(STCategoryRule * leafRule, STCategoryNode * root,
|
||||
STGlobals * g)
|
||||
{
|
||||
STCategoryRule* rule;
|
||||
STCategoryNode* node;
|
||||
STCategoryRule *rule;
|
||||
STCategoryNode *node;
|
||||
|
||||
rule = (STCategoryRule *) calloc(1, sizeof(STCategoryRule));
|
||||
if (!rule)
|
||||
|
@ -267,37 +278,35 @@ int ProcessCategoryLeafRule(STCategoryRule* leafRule, STCategoryNode *root, STGl
|
|||
** Rule has all the children of category as patterns. Sets up the tree so that
|
||||
** the parent child relationship is honored.
|
||||
*/
|
||||
int ProcessCategoryParentRule(STCategoryRule* parentRule, STCategoryNode *root, STGlobals* g)
|
||||
int
|
||||
ProcessCategoryParentRule(STCategoryRule * parentRule, STCategoryNode * root,
|
||||
STGlobals * g)
|
||||
{
|
||||
STCategoryNode* node;
|
||||
STCategoryNode* child;
|
||||
STCategoryNode *node;
|
||||
STCategoryNode *child;
|
||||
PRUint32 i;
|
||||
|
||||
/* Find the parent node in the tree. If not make one and add it into the tree */
|
||||
node = findCategoryNode(parentRule->categoryName, g);
|
||||
if (!node)
|
||||
{
|
||||
if (!node) {
|
||||
node = NewCategoryNode(parentRule->categoryName, root, g);
|
||||
if (!node)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* For every child node, Find/Create it and make it the child of this node */
|
||||
for(i = 0; i < parentRule->npats; i++)
|
||||
{
|
||||
for (i = 0; i < parentRule->npats; i++) {
|
||||
child = findCategoryNode(parentRule->pats[i], g);
|
||||
if (!child)
|
||||
{
|
||||
if (!child) {
|
||||
child = NewCategoryNode(parentRule->pats[i], node, g);
|
||||
if (!child)
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
/* Reparent child to node. This is because when we created the node
|
||||
** we would have created it as the child of root. Now we need to
|
||||
** remove it from root's child list and add it into this node
|
||||
*/
|
||||
** we would have created it as the child of root. Now we need to
|
||||
** remove it from root's child list and add it into this node
|
||||
*/
|
||||
ReParent(node, child);
|
||||
}
|
||||
}
|
||||
|
@ -312,7 +321,8 @@ int ProcessCategoryParentRule(STCategoryRule* parentRule, STCategoryNode *root,
|
|||
** each callsite, creates a tree of these categories and makes a list of these
|
||||
** patterns in order for matching
|
||||
*/
|
||||
int initCategories(STGlobals* g)
|
||||
int
|
||||
initCategories(STGlobals * g)
|
||||
{
|
||||
FILE *fp;
|
||||
char buf[1024], *in;
|
||||
|
@ -321,8 +331,7 @@ int initCategories(STGlobals* g)
|
|||
STCategoryRule rule;
|
||||
|
||||
fp = fopen(g->mCommandLineOptions.mCategoryFile, "r");
|
||||
if (!fp)
|
||||
{
|
||||
if (!fp) {
|
||||
/* It isnt an error to not have a categories file */
|
||||
REPORT_INFO("No categories file.");
|
||||
return -1;
|
||||
|
@ -333,11 +342,10 @@ int initCategories(STGlobals* g)
|
|||
|
||||
memset(&rule, 0, sizeof(rule));
|
||||
|
||||
while (fgets(buf, sizeof(buf), fp) != NULL)
|
||||
{
|
||||
while (fgets(buf, sizeof(buf), fp) != NULL) {
|
||||
/* Lose the \n */
|
||||
n = strlen(buf);
|
||||
if (buf[n-1] == '\n')
|
||||
if (buf[n - 1] == '\n')
|
||||
buf[--n] = '\0';
|
||||
in = buf;
|
||||
|
||||
|
@ -346,12 +354,11 @@ int initCategories(STGlobals* g)
|
|||
continue;
|
||||
|
||||
/* skip empty lines. If we are in a rule, end the rule. */
|
||||
while(*in && isspace(*in))
|
||||
while (*in && isspace(*in))
|
||||
in++;
|
||||
if (*in == '\0') {
|
||||
if (inrule)
|
||||
{
|
||||
/* End the rule : leaf or non-leaf*/
|
||||
if (inrule) {
|
||||
/* End the rule : leaf or non-leaf */
|
||||
if (leaf)
|
||||
ProcessCategoryLeafRule(&rule, &g->mCategoryRoot, g);
|
||||
else
|
||||
|
@ -364,13 +371,11 @@ int initCategories(STGlobals* g)
|
|||
}
|
||||
|
||||
/* if we are in a rule acculumate */
|
||||
if (inrule)
|
||||
{
|
||||
if (inrule) {
|
||||
rule.pats[rule.npats] = strdup(in);
|
||||
rule.patlen[rule.npats++] = strlen(in);
|
||||
}
|
||||
else if (*in == '<')
|
||||
{
|
||||
else if (*in == '<') {
|
||||
/* Start a category */
|
||||
inrule = PR_TRUE;
|
||||
leaf = PR_TRUE;
|
||||
|
@ -378,15 +383,14 @@ int initCategories(STGlobals* g)
|
|||
/* Get the category name */
|
||||
in++;
|
||||
n = strlen(in);
|
||||
if (in[n-1] == '>')
|
||||
in[n-1] = '\0';
|
||||
if (in[n - 1] == '>')
|
||||
in[n - 1] = '\0';
|
||||
rule.categoryName = strdup(in);
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
/* this is a non-leaf category. Should be of the form CategoryName
|
||||
** followed by list of child category names one per line
|
||||
*/
|
||||
** followed by list of child category names one per line
|
||||
*/
|
||||
inrule = PR_TRUE;
|
||||
leaf = PR_FALSE;
|
||||
rule.categoryName = strdup(in);
|
||||
|
@ -394,9 +398,8 @@ int initCategories(STGlobals* g)
|
|||
}
|
||||
|
||||
/* If we were in a rule when processing the last line, end the rule */
|
||||
if (inrule)
|
||||
{
|
||||
/* End the rule : leaf or non-leaf*/
|
||||
if (inrule) {
|
||||
/* End the rule : leaf or non-leaf */
|
||||
if (leaf)
|
||||
ProcessCategoryLeafRule(&rule, &g->mCategoryRoot, g);
|
||||
else
|
||||
|
@ -405,9 +408,9 @@ int initCategories(STGlobals* g)
|
|||
}
|
||||
|
||||
/* Add the final "uncategorized" category. We make new memory locations
|
||||
** for all these to conform to the general principle of all strings are allocated
|
||||
** so it makes release logic very simple.
|
||||
*/
|
||||
** for all these to conform to the general principle of all strings are allocated
|
||||
** so it makes release logic very simple.
|
||||
*/
|
||||
memset(&rule, 0, sizeof(rule));
|
||||
rule.categoryName = strdup("uncategorized");
|
||||
rule.pats[0] = strdup("");
|
||||
|
@ -424,39 +427,37 @@ int initCategories(STGlobals* g)
|
|||
** Returns the corresponding node if callsite matches the rule. Rule is a sequence
|
||||
** of patterns that must match contiguously the callsite.
|
||||
*/
|
||||
int callsiteMatchesRule(tmcallsite* aCallsite, STCategoryRule* aRule)
|
||||
int
|
||||
callsiteMatchesRule(tmcallsite * aCallsite, STCategoryRule * aRule)
|
||||
{
|
||||
PRUint32 patnum = 0;
|
||||
const char *methodName = NULL;
|
||||
|
||||
while (patnum < aRule->npats && aCallsite && aCallsite->method)
|
||||
{
|
||||
while (patnum < aRule->npats && aCallsite && aCallsite->method) {
|
||||
methodName = tmmethodnode_name(aCallsite->method);
|
||||
if (!methodName)
|
||||
return 0;
|
||||
if (!*aRule->pats[patnum] || !strncmp(methodName, aRule->pats[patnum], aRule->patlen[patnum]))
|
||||
{
|
||||
if (!*aRule->pats[patnum]
|
||||
|| !strncmp(methodName, aRule->pats[patnum],
|
||||
aRule->patlen[patnum])) {
|
||||
/* We have matched so far. Proceed up the stack and to the next pattern */
|
||||
patnum++;
|
||||
aCallsite = aCallsite->parent;
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
/* Deal with mismatch */
|
||||
if (patnum > 0)
|
||||
{
|
||||
if (patnum > 0) {
|
||||
/* contiguous mismatch. Stop */
|
||||
return 0;
|
||||
}
|
||||
/* We still haven't matched the first pattern. Proceed up the stack without
|
||||
** moving to the next pattern.
|
||||
*/
|
||||
** moving to the next pattern.
|
||||
*/
|
||||
aCallsite = aCallsite->parent;
|
||||
}
|
||||
}
|
||||
|
||||
if (patnum == aRule->npats)
|
||||
{
|
||||
if (patnum == aRule->npats) {
|
||||
/* all patterns matched. We have a winner. */
|
||||
#if defined(DEBUG_dp) && 0
|
||||
fprintf(stderr, "[%s] match\n", aRule->categoryName);
|
||||
|
@ -479,23 +480,22 @@ PRUint32 _gMatchRules = 0;
|
|||
** Runs through all rules and returns the node corresponding to
|
||||
** a match of the allocation.
|
||||
*/
|
||||
STCategoryNode* matchAllocation(STGlobals* g, STAllocation* aAllocation)
|
||||
STCategoryNode *
|
||||
matchAllocation(STGlobals * g, STAllocation * aAllocation)
|
||||
{
|
||||
#ifdef DEBUG_dp
|
||||
PRIntervalTime start = PR_IntervalNow();
|
||||
#endif
|
||||
PRUint32 rulenum;
|
||||
STCategoryNode* node = NULL;
|
||||
STCategoryRule* rule;
|
||||
STCategoryNode *node = NULL;
|
||||
STCategoryRule *rule;
|
||||
|
||||
for (rulenum = 0; rulenum < g->mNRules; rulenum++)
|
||||
{
|
||||
for (rulenum = 0; rulenum < g->mNRules; rulenum++) {
|
||||
#ifdef DEBUG_dp
|
||||
_gMatchRules++;
|
||||
#endif
|
||||
rule = g->mCategoryRules[rulenum];
|
||||
if (callsiteMatchesRule(aAllocation->mEvents[0].mCallsite, rule))
|
||||
{
|
||||
if (callsiteMatchesRule(aAllocation->mEvents[0].mCallsite, rule)) {
|
||||
node = rule->node;
|
||||
break;
|
||||
}
|
||||
|
@ -516,59 +516,68 @@ STCategoryNode* matchAllocation(STGlobals* g, STAllocation* aAllocation)
|
|||
** The root of the tree is in the globls as the tree is dependent on the
|
||||
** category file (options) rather than the run.
|
||||
*/
|
||||
int categorizeAllocation(STOptions* inOptions, STContext* inContext, STAllocation* aAllocation, STGlobals* g)
|
||||
int
|
||||
categorizeAllocation(STOptions * inOptions, STContext * inContext,
|
||||
STAllocation * aAllocation, STGlobals * g)
|
||||
{
|
||||
/* Run through the rules in order to see if this allcation matches
|
||||
** any of them.
|
||||
*/
|
||||
STCategoryNode* node;
|
||||
** any of them.
|
||||
*/
|
||||
STCategoryNode *node;
|
||||
|
||||
node = matchAllocation(g, aAllocation);
|
||||
if (!node)
|
||||
{
|
||||
if (!node) {
|
||||
/* ugh! it should atleast go into the "uncategorized" node. wierd!
|
||||
*/
|
||||
*/
|
||||
REPORT_ERROR(__LINE__, categorizeAllocation);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Create run for node if not already */
|
||||
if (!node->runs[inContext->mIndex])
|
||||
{
|
||||
if (!node->runs[inContext->mIndex]) {
|
||||
/*
|
||||
** Create run with positive timestamp as we can harvest it later
|
||||
** for callsite details summarization
|
||||
*/
|
||||
node->runs[inContext->mIndex] = createRun(inContext, PR_IntervalNow());
|
||||
if (!node->runs[inContext->mIndex])
|
||||
{
|
||||
** Create run with positive timestamp as we can harvest it later
|
||||
** for callsite details summarization
|
||||
*/
|
||||
node->runs[inContext->mIndex] =
|
||||
createRun(inContext, PR_IntervalNow());
|
||||
if (!node->runs[inContext->mIndex]) {
|
||||
REPORT_ERROR(__LINE__, categorizeAllocation_No_Memory);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Add allocation into node. We expand the table of allocations in steps */
|
||||
if (node->runs[inContext->mIndex]->mAllocationCount % ST_ALLOC_STEP == 0)
|
||||
{
|
||||
if (node->runs[inContext->mIndex]->mAllocationCount % ST_ALLOC_STEP == 0) {
|
||||
/* Need more space */
|
||||
STAllocation** allocs;
|
||||
allocs = (STAllocation**) realloc(node->runs[inContext->mIndex]->mAllocations,
|
||||
(node->runs[inContext->mIndex]->mAllocationCount + ST_ALLOC_STEP) * sizeof(STAllocation*));
|
||||
if (!allocs)
|
||||
{
|
||||
STAllocation **allocs;
|
||||
|
||||
allocs =
|
||||
(STAllocation **) realloc(node->runs[inContext->mIndex]->
|
||||
mAllocations,
|
||||
(node->runs[inContext->mIndex]->
|
||||
mAllocationCount +
|
||||
ST_ALLOC_STEP) *
|
||||
sizeof(STAllocation *));
|
||||
if (!allocs) {
|
||||
REPORT_ERROR(__LINE__, categorizeAllocation_No_Memory);
|
||||
return -1;
|
||||
}
|
||||
node->runs[inContext->mIndex]->mAllocations = allocs;
|
||||
}
|
||||
node->runs[inContext->mIndex]->mAllocations[node->runs[inContext->mIndex]->mAllocationCount++] = aAllocation;
|
||||
node->runs[inContext->mIndex]->mAllocations[node->
|
||||
runs[inContext->mIndex]->
|
||||
mAllocationCount++] =
|
||||
aAllocation;
|
||||
|
||||
/*
|
||||
** Make sure run's stats are calculated. We dont go update the parents of allocation
|
||||
** at this time. That will happen when we focus on this category. This updating of
|
||||
** stats will provide us fast categoryreports.
|
||||
*/
|
||||
recalculateAllocationCost(inOptions, inContext, node->runs[inContext->mIndex], aAllocation, PR_FALSE);
|
||||
** Make sure run's stats are calculated. We dont go update the parents of allocation
|
||||
** at this time. That will happen when we focus on this category. This updating of
|
||||
** stats will provide us fast categoryreports.
|
||||
*/
|
||||
recalculateAllocationCost(inOptions, inContext,
|
||||
node->runs[inContext->mIndex], aAllocation,
|
||||
PR_FALSE);
|
||||
|
||||
/* Propogate upwards the statistics */
|
||||
/* XXX */
|
||||
|
@ -578,33 +587,39 @@ int categorizeAllocation(STOptions* inOptions, STContext* inContext, STAllocatio
|
|||
return 0;
|
||||
}
|
||||
|
||||
typedef PRBool STCategoryNodeProcessor(STRequest* inRequest, STOptions* inOptions, STContext* inContext, void* clientData, STCategoryNode* node);
|
||||
typedef PRBool STCategoryNodeProcessor(STRequest * inRequest,
|
||||
STOptions * inOptions,
|
||||
STContext * inContext,
|
||||
void *clientData,
|
||||
STCategoryNode * node);
|
||||
|
||||
PRBool freeNodeRunProcessor(STRequest* inRequest, STOptions* inOptions, STContext* inContext, void* clientData, STCategoryNode* node)
|
||||
PRBool
|
||||
freeNodeRunProcessor(STRequest * inRequest, STOptions * inOptions,
|
||||
STContext * inContext, void *clientData,
|
||||
STCategoryNode * node)
|
||||
{
|
||||
if (node->runs && node->runs[inContext->mIndex])
|
||||
{
|
||||
if (node->runs && node->runs[inContext->mIndex]) {
|
||||
freeRun(node->runs[inContext->mIndex]);
|
||||
node->runs[inContext->mIndex] = NULL;
|
||||
}
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
PRBool freeNodeRunsProcessor(STRequest* inRequest, STOptions* inOptions, STContext* inContext, void* clientData, STCategoryNode* node)
|
||||
PRBool
|
||||
freeNodeRunsProcessor(STRequest * inRequest, STOptions * inOptions,
|
||||
STContext * inContext, void *clientData,
|
||||
STCategoryNode * node)
|
||||
{
|
||||
if (node->runs)
|
||||
{
|
||||
if (node->runs) {
|
||||
PRUint32 loop = 0;
|
||||
|
||||
for(loop = 0; loop < globals.mCommandLineOptions.mContexts; loop++)
|
||||
{
|
||||
if (node->runs[loop])
|
||||
{
|
||||
|
||||
for (loop = 0; loop < globals.mCommandLineOptions.mContexts; loop++) {
|
||||
if (node->runs[loop]) {
|
||||
freeRun(node->runs[loop]);
|
||||
node->runs[loop] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
free(node->runs);
|
||||
node->runs = NULL;
|
||||
}
|
||||
|
@ -613,23 +628,32 @@ PRBool freeNodeRunsProcessor(STRequest* inRequest, STOptions* inOptions, STConte
|
|||
}
|
||||
|
||||
#if defined(DEBUG_dp)
|
||||
PRBool printNodeProcessor(STRequest* inRequest, STOptions* inOptions, STContext* inContext, void* clientData, STCategoryNode* node)
|
||||
PRBool
|
||||
printNodeProcessor(STRequest * inRequest, STOptions * inOptions,
|
||||
STContext * inContext, void *clientData,
|
||||
STCategoryNode * node)
|
||||
{
|
||||
STCategoryNode* root = (STCategoryNode*) clientData;
|
||||
STCategoryNode *root = (STCategoryNode *) clientData;
|
||||
|
||||
fprintf(stderr, "%-25s [ %9s size", node->categoryName,
|
||||
FormatNumber(node->run ? node->run->mStats[inContext->mIndex].mSize:0));
|
||||
FormatNumber(node->run ? node->run->mStats[inContext->mIndex].
|
||||
mSize : 0));
|
||||
fprintf(stderr, ", %5.1f%%",
|
||||
node->run ? ((double)node->run->mStats[inContext->mIndex].mSize / root->run->mStats[inContext->mIndex].mSize * 100):0);
|
||||
node->run ? ((double) node->run->mStats[inContext->mIndex].mSize /
|
||||
root->run->mStats[inContext->mIndex].mSize *
|
||||
100) : 0);
|
||||
fprintf(stderr, ", %7s allocations ]\n",
|
||||
FormatNumber(node->run ? node->run->mStats[inContext->mIndex].mCompositeCount:0));
|
||||
FormatNumber(node->run ? node->run->mStats[inContext->mIndex].
|
||||
mCompositeCount : 0));
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
typedef struct __struct_optcon {
|
||||
STOptions* mOptions;
|
||||
STContext* mContext;
|
||||
typedef struct __struct_optcon
|
||||
{
|
||||
STOptions *mOptions;
|
||||
STContext *mContext;
|
||||
}
|
||||
optcon;
|
||||
|
||||
|
@ -639,12 +663,13 @@ optcon;
|
|||
** qsort callback.
|
||||
** Compare the nodes as specified by the options.
|
||||
*/
|
||||
int compareNode(const void* aNode1, const void* aNode2, void* aContext)
|
||||
int
|
||||
compareNode(const void *aNode1, const void *aNode2, void *aContext)
|
||||
{
|
||||
int retval = 0;
|
||||
STCategoryNode* node1, * node2;
|
||||
STCategoryNode *node1, *node2;
|
||||
PRUint32 a, b;
|
||||
optcon *oc = (optcon*)aContext;
|
||||
optcon *oc = (optcon *) aContext;
|
||||
|
||||
if (!aNode1 || !aNode2 || !oc->mOptions || !oc->mContext)
|
||||
return 0;
|
||||
|
@ -652,37 +677,49 @@ int compareNode(const void* aNode1, const void* aNode2, void* aContext)
|
|||
node1 = *((STCategoryNode **) aNode1);
|
||||
node2 = *((STCategoryNode **) aNode2);
|
||||
|
||||
if (node1 && node2)
|
||||
{
|
||||
if (oc->mOptions->mOrderBy == ST_COUNT)
|
||||
{
|
||||
a = (node1->runs[oc->mContext->mIndex]) ? node1->runs[oc->mContext->mIndex]->mStats[oc->mContext->mIndex].mCompositeCount : 0;
|
||||
b = (node2->runs[oc->mContext->mIndex]) ? node2->runs[oc->mContext->mIndex]->mStats[oc->mContext->mIndex].mCompositeCount : 0;
|
||||
if (node1 && node2) {
|
||||
if (oc->mOptions->mOrderBy == ST_COUNT) {
|
||||
a = (node1->runs[oc->mContext->mIndex]) ? node1->runs[oc->
|
||||
mContext->
|
||||
mIndex]->
|
||||
mStats[oc->mContext->mIndex].mCompositeCount : 0;
|
||||
b = (node2->runs[oc->mContext->mIndex]) ? node2->runs[oc->
|
||||
mContext->
|
||||
mIndex]->
|
||||
mStats[oc->mContext->mIndex].mCompositeCount : 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
/* Default is by size */
|
||||
a = (node1->runs[oc->mContext->mIndex]) ? node1->runs[oc->mContext->mIndex]->mStats[oc->mContext->mIndex].mSize : 0;
|
||||
b = (node2->runs[oc->mContext->mIndex]) ? node2->runs[oc->mContext->mIndex]->mStats[oc->mContext->mIndex].mSize : 0;
|
||||
a = (node1->runs[oc->mContext->mIndex]) ? node1->runs[oc->
|
||||
mContext->
|
||||
mIndex]->
|
||||
mStats[oc->mContext->mIndex].mSize : 0;
|
||||
b = (node2->runs[oc->mContext->mIndex]) ? node2->runs[oc->
|
||||
mContext->
|
||||
mIndex]->
|
||||
mStats[oc->mContext->mIndex].mSize : 0;
|
||||
}
|
||||
if (a < b)
|
||||
retval = __LINE__;
|
||||
else
|
||||
retval = - __LINE__;
|
||||
retval = -__LINE__;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
PRBool sortNodeProcessor(STRequest* inRequest, STOptions* inOptions, STContext* inContext, void* clientData, STCategoryNode* node)
|
||||
PRBool
|
||||
sortNodeProcessor(STRequest * inRequest, STOptions * inOptions,
|
||||
STContext * inContext, void *clientData,
|
||||
STCategoryNode * node)
|
||||
{
|
||||
if (node->nchildren)
|
||||
{
|
||||
if (node->nchildren) {
|
||||
optcon context;
|
||||
|
||||
context.mOptions = inOptions;
|
||||
context.mContext = inContext;
|
||||
|
||||
NS_QuickSort(node->children, node->nchildren, sizeof(STCategoryNode *), compareNode, &context);
|
||||
NS_QuickSort(node->children, node->nchildren,
|
||||
sizeof(STCategoryNode *), compareNode, &context);
|
||||
}
|
||||
|
||||
return PR_TRUE;
|
||||
|
@ -698,44 +735,43 @@ PRBool sortNodeProcessor(STRequest* inRequest, STOptions* inOptions, STContext*
|
|||
*/
|
||||
#define MODINC(n, mod) ((n+1) % mod)
|
||||
|
||||
void walkTree(STCategoryNode* root, STCategoryNodeProcessor func, STRequest* inRequest, STOptions* inOptions, STContext* inContext, void *clientData, int maxdepth)
|
||||
void
|
||||
walkTree(STCategoryNode * root, STCategoryNodeProcessor func,
|
||||
STRequest * inRequest, STOptions * inOptions, STContext * inContext,
|
||||
void *clientData, int maxdepth)
|
||||
{
|
||||
STCategoryNode* nodes[1024], *node;
|
||||
STCategoryNode *nodes[1024], *node;
|
||||
PRUint32 begin, end, i;
|
||||
int ret = 0;
|
||||
int curdepth = 0, ncurdepth = 0;
|
||||
|
||||
nodes[0] = root;
|
||||
begin = 0; end = 1;
|
||||
begin = 0;
|
||||
end = 1;
|
||||
ncurdepth = 1;
|
||||
while (begin != end)
|
||||
{
|
||||
while (begin != end) {
|
||||
node = nodes[begin];
|
||||
ret = (*func)(inRequest, inOptions, inContext, clientData, node);
|
||||
if (ret == PR_FALSE)
|
||||
{
|
||||
ret = (*func) (inRequest, inOptions, inContext, clientData, node);
|
||||
if (ret == PR_FALSE) {
|
||||
/* Abort */
|
||||
break;
|
||||
}
|
||||
begin = MODINC(begin, 1024);
|
||||
for (i = 0; i < node->nchildren; i++)
|
||||
{
|
||||
for (i = 0; i < node->nchildren; i++) {
|
||||
nodes[end] = node->children[i];
|
||||
end = MODINC(end, 1024);
|
||||
}
|
||||
/* Depth tracking. Do it only if walkTree is contrained by a maxdepth */
|
||||
if (maxdepth > 0 && --ncurdepth == 0)
|
||||
{
|
||||
if (maxdepth > 0 && --ncurdepth == 0) {
|
||||
/*
|
||||
** No more children in current depth. The rest of the nodes
|
||||
** we have in our list should be nodes in the depth below us.
|
||||
*/
|
||||
** No more children in current depth. The rest of the nodes
|
||||
** we have in our list should be nodes in the depth below us.
|
||||
*/
|
||||
ncurdepth = (begin < end) ? (end - begin) : (1024 - begin + end);
|
||||
if (++curdepth > maxdepth)
|
||||
{
|
||||
if (++curdepth > maxdepth) {
|
||||
/*
|
||||
** Gone too deep. Stop.
|
||||
*/
|
||||
** Gone too deep. Stop.
|
||||
*/
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -743,10 +779,12 @@ void walkTree(STCategoryNode* root, STCategoryNodeProcessor func, STRequest* inR
|
|||
return;
|
||||
}
|
||||
|
||||
int freeRule(STCategoryRule* rule)
|
||||
int
|
||||
freeRule(STCategoryRule * rule)
|
||||
{
|
||||
PRUint32 i;
|
||||
char *p = (char *)rule->categoryName;
|
||||
char *p = (char *) rule->categoryName;
|
||||
|
||||
PR_FREEIF(p);
|
||||
|
||||
for (i = 0; i < rule->npats; i++)
|
||||
|
@ -756,43 +794,44 @@ int freeRule(STCategoryRule* rule)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void freeNodeRuns(STCategoryNode* root)
|
||||
void
|
||||
freeNodeRuns(STCategoryNode * root)
|
||||
{
|
||||
walkTree(root, freeNodeRunsProcessor, NULL, NULL, NULL, NULL, 0);
|
||||
walkTree(root, freeNodeRunsProcessor, NULL, NULL, NULL, NULL, 0);
|
||||
}
|
||||
|
||||
void freeNodeMap(STGlobals* g)
|
||||
void
|
||||
freeNodeMap(STGlobals * g)
|
||||
{
|
||||
PRUint32 i;
|
||||
|
||||
/* all nodes are in the map table. Just delete all of those. */
|
||||
for(i = 0; i < g->mNCategoryMap; i++)
|
||||
{
|
||||
for (i = 0; i < g->mNCategoryMap; i++) {
|
||||
free(g->mCategoryMap[i]->node);
|
||||
free(g->mCategoryMap[i]);
|
||||
}
|
||||
free(g->mCategoryMap);
|
||||
}
|
||||
|
||||
int freeCategories(STGlobals* g)
|
||||
int
|
||||
freeCategories(STGlobals * g)
|
||||
{
|
||||
PRUint32 i;
|
||||
|
||||
/*
|
||||
** walk the tree and free runs held in nodes
|
||||
*/
|
||||
** walk the tree and free runs held in nodes
|
||||
*/
|
||||
freeNodeRuns(&g->mCategoryRoot);
|
||||
|
||||
/*
|
||||
** delete nodemap. This is the where nodes get deleted.
|
||||
*/
|
||||
** delete nodemap. This is the where nodes get deleted.
|
||||
*/
|
||||
freeNodeMap(g);
|
||||
|
||||
/*
|
||||
** delete rule stuff
|
||||
*/
|
||||
for (i = 0; i < g->mNRules; i++)
|
||||
{
|
||||
** delete rule stuff
|
||||
*/
|
||||
for (i = 0; i < g->mNRules; i++) {
|
||||
freeRule(g->mCategoryRules[i]);
|
||||
}
|
||||
free(g->mCategoryRules);
|
||||
|
@ -807,48 +846,56 @@ int freeCategories(STGlobals* g)
|
|||
** categorize all the allocations of the run using the rules into
|
||||
** a tree rooted at globls.mCategoryRoot
|
||||
*/
|
||||
int categorizeRun(STOptions* inOptions, STContext* inContext, const STRun* aRun, STGlobals* g)
|
||||
int
|
||||
categorizeRun(STOptions * inOptions, STContext * inContext,
|
||||
const STRun * aRun, STGlobals * g)
|
||||
{
|
||||
PRUint32 i;
|
||||
|
||||
#if defined(DEBUG_dp)
|
||||
PRIntervalTime start = PR_IntervalNow();
|
||||
|
||||
fprintf(stderr, "DEBUG: categorizing run...\n");
|
||||
#endif
|
||||
|
||||
/*
|
||||
** First, cleanup our tree
|
||||
*/
|
||||
walkTree(&g->mCategoryRoot, freeNodeRunProcessor, NULL, inOptions, inContext, NULL, 0);
|
||||
** First, cleanup our tree
|
||||
*/
|
||||
walkTree(&g->mCategoryRoot, freeNodeRunProcessor, NULL, inOptions,
|
||||
inContext, NULL, 0);
|
||||
|
||||
if (g->mNCategoryMap > 0)
|
||||
{
|
||||
for (i = 0; i < aRun->mAllocationCount; i++)
|
||||
{
|
||||
categorizeAllocation(inOptions, inContext, aRun->mAllocations[i], g);
|
||||
if (g->mNCategoryMap > 0) {
|
||||
for (i = 0; i < aRun->mAllocationCount; i++) {
|
||||
categorizeAllocation(inOptions, inContext, aRun->mAllocations[i],
|
||||
g);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** the run is always going to be the one corresponding to the root node
|
||||
*/
|
||||
** the run is always going to be the one corresponding to the root node
|
||||
*/
|
||||
g->mCategoryRoot.runs[inContext->mIndex] = (STRun *) aRun;
|
||||
g->mCategoryRoot.categoryName = ST_ROOT_CATEGORY_NAME;
|
||||
|
||||
#if defined(DEBUG_dp)
|
||||
fprintf(stderr, "DEBUG: categorizing ends: %dms [%d rules, %d allocations]\n",
|
||||
PR_IntervalToMilliseconds(PR_IntervalNow() - start), g->mNRules, aRun->mAllocationCount);
|
||||
fprintf(stderr,
|
||||
"DEBUG: categorizing ends: %dms [%d rules, %d allocations]\n",
|
||||
PR_IntervalToMilliseconds(PR_IntervalNow() - start), g->mNRules,
|
||||
aRun->mAllocationCount);
|
||||
fprintf(stderr, "DEBUG: match : %dms [%d calls, %d rule-compares]\n",
|
||||
PR_IntervalToMilliseconds(_gMatchTime),
|
||||
_gMatchCount, _gMatchRules);
|
||||
PR_IntervalToMilliseconds(_gMatchTime), _gMatchCount,
|
||||
_gMatchRules);
|
||||
#endif
|
||||
|
||||
/*
|
||||
** sort the tree based on our sort criterion
|
||||
*/
|
||||
walkTree(&g->mCategoryRoot, sortNodeProcessor, NULL, inOptions, inContext, NULL, 0);
|
||||
** sort the tree based on our sort criterion
|
||||
*/
|
||||
walkTree(&g->mCategoryRoot, sortNodeProcessor, NULL, inOptions, inContext,
|
||||
NULL, 0);
|
||||
|
||||
#if defined(DEBUG_dp)
|
||||
walkTree(&g->mCategoryRoot, printNodeProcessor, NULL, inOptions, inContext, &g->mCategoryRoot, 0);
|
||||
walkTree(&g->mCategoryRoot, printNodeProcessor, NULL, inOptions,
|
||||
inContext, &g->mCategoryRoot, 0);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
@ -861,63 +908,70 @@ int categorizeRun(STOptions* inOptions, STContext* inContext, const STRun* aRun,
|
|||
** Generate the category report - a list of all categories and details about each
|
||||
** depth parameter controls how deep we traverse the category tree.
|
||||
*/
|
||||
PRBool displayCategoryNodeProcessor(STRequest* inRequest, STOptions* inOptions, STContext* inContext, void* clientData, STCategoryNode* node)
|
||||
PRBool
|
||||
displayCategoryNodeProcessor(STRequest * inRequest, STOptions * inOptions,
|
||||
STContext * inContext, void *clientData,
|
||||
STCategoryNode * node)
|
||||
{
|
||||
STCategoryNode* root = (STCategoryNode *) clientData;
|
||||
STCategoryNode *root = (STCategoryNode *) clientData;
|
||||
PRUint32 byteSize = 0, heapCost = 0, count = 0;
|
||||
double percent = 0;
|
||||
STOptions customOps;
|
||||
|
||||
if (node->runs[inContext->mIndex])
|
||||
{
|
||||
if (node->runs[inContext->mIndex]) {
|
||||
/*
|
||||
** Byte size
|
||||
*/
|
||||
byteSize = node->runs[inContext->mIndex]->mStats[inContext->mIndex].mSize;
|
||||
** Byte size
|
||||
*/
|
||||
byteSize =
|
||||
node->runs[inContext->mIndex]->mStats[inContext->mIndex].mSize;
|
||||
|
||||
/*
|
||||
** Composite count
|
||||
*/
|
||||
count = node->runs[inContext->mIndex]->mStats[inContext->mIndex].mCompositeCount;
|
||||
** Composite count
|
||||
*/
|
||||
count =
|
||||
node->runs[inContext->mIndex]->mStats[inContext->mIndex].
|
||||
mCompositeCount;
|
||||
|
||||
/*
|
||||
** Heap operation cost
|
||||
**/
|
||||
heapCost = node->runs[inContext->mIndex]->mStats[inContext->mIndex].mHeapRuntimeCost;
|
||||
** Heap operation cost
|
||||
**/
|
||||
heapCost =
|
||||
node->runs[inContext->mIndex]->mStats[inContext->mIndex].
|
||||
mHeapRuntimeCost;
|
||||
|
||||
/*
|
||||
** % of total size
|
||||
*/
|
||||
if (root->runs[inContext->mIndex])
|
||||
{
|
||||
percent = ((double) byteSize) / root->runs[inContext->mIndex]->mStats[inContext->mIndex].mSize * 100;
|
||||
** % of total size
|
||||
*/
|
||||
if (root->runs[inContext->mIndex]) {
|
||||
percent =
|
||||
((double) byteSize) /
|
||||
root->runs[inContext->mIndex]->mStats[inContext->mIndex].
|
||||
mSize * 100;
|
||||
}
|
||||
}
|
||||
|
||||
PR_fprintf(inRequest->mFD,
|
||||
" <tr>\n"
|
||||
" <td>");
|
||||
PR_fprintf(inRequest->mFD, " <tr>\n" " <td>");
|
||||
|
||||
/* a link to topcallsites report with focus on category */
|
||||
memcpy(&customOps, inOptions, sizeof(customOps));
|
||||
PR_snprintf(customOps.mCategoryName, sizeof(customOps.mCategoryName), "%s", node->categoryName);
|
||||
PR_snprintf(customOps.mCategoryName, sizeof(customOps.mCategoryName),
|
||||
"%s", node->categoryName);
|
||||
|
||||
htmlAnchor(inRequest, "top_callsites.html", node->categoryName, NULL, "category-callsites", &customOps);
|
||||
htmlAnchor(inRequest, "top_callsites.html", node->categoryName, NULL,
|
||||
"category-callsites", &customOps);
|
||||
PR_fprintf(inRequest->mFD,
|
||||
"</td>\n"
|
||||
" <td align=right>%u</td>\n"
|
||||
"</td>\n" " <td align=right>%u</td>\n"
|
||||
" <td align=right>%4.1f%%</td>\n"
|
||||
" <td align=right>%u</td>\n"
|
||||
" <td align=right>" ST_MICROVAL_FORMAT "</td>\n"
|
||||
" </tr>\n",
|
||||
byteSize, percent, count,
|
||||
ST_MICROVAL_PRINTABLE(heapCost));
|
||||
" <td align=right>%u</td>\n" " <td align=right>"
|
||||
ST_MICROVAL_FORMAT "</td>\n" " </tr>\n", byteSize, percent,
|
||||
count, ST_MICROVAL_PRINTABLE(heapCost));
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
|
||||
int displayCategoryReport(STRequest* inRequest, STCategoryNode *root, int depth)
|
||||
int
|
||||
displayCategoryReport(STRequest * inRequest, STCategoryNode * root, int depth)
|
||||
{
|
||||
PR_fprintf(inRequest->mFD,
|
||||
"<table class=\"category-list data\">\n"
|
||||
|
@ -926,11 +980,10 @@ int displayCategoryReport(STRequest* inRequest, STCategoryNode *root, int depth)
|
|||
" <th>Composite Byte Size</th>\n"
|
||||
" <th>%% of Total Size</th>\n"
|
||||
" <th>Heap Object Count</th>\n"
|
||||
" <th>Composite Heap Operations Seconds</th>\n"
|
||||
" </tr>\n"
|
||||
);
|
||||
" <th>Composite Heap Operations Seconds</th>\n" " </tr>\n");
|
||||
|
||||
walkTree(root, displayCategoryNodeProcessor, inRequest, &inRequest->mOptions, inRequest->mContext, root, depth);
|
||||
walkTree(root, displayCategoryNodeProcessor, inRequest,
|
||||
&inRequest->mOptions, inRequest->mContext, root, depth);
|
||||
|
||||
PR_fprintf(inRequest->mFD, "</table>\n");
|
||||
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Загрузка…
Ссылка в новой задаче