/* -----------------------------------------------------------------------------
- * $Id: ProfHeap.c,v 1.32 2001/11/29 16:38:13 simonmar Exp $
+ * $Id: ProfHeap.c,v 1.39 2002/11/01 11:05:46 simonmar Exp $
*
* (c) The GHC Team, 1998-2000
*
#include "Arena.h"
#include "Printer.h"
+#include <string.h>
+
/* -----------------------------------------------------------------------------
* era stores the current time period. It is the same as the
* number of censuses that have been performed.
* RESTRICTION:
* era must be no longer than LDV_SHIFT (15 or 30) bits.
* Invariants:
- * era is initialized to 0 in initHeapProfiling().
+ * era is initialized to 1 in initHeapProfiling().
*
* max_era is initialized to 2^LDV_SHIFT in initHeapProfiling().
* When era reaches max_era, the profiling stops because a closure can
int drag_total;
} Census;
-Census *censuses = NULL;
-nat n_censuses = 0;
+static Census *censuses = NULL;
+static nat n_censuses = 0;
#ifdef PROFILING
static void aggregateCensusInfo( void );
#ifdef PROFILING
case HEAP_BY_CCS:
- return ((StgClosure *)p)->header.prof.ccs;
+ return p->header.prof.ccs;
case HEAP_BY_MOD:
- return ((StgClosure *)p)->header.prof.ccs->cc->module;
+ return p->header.prof.ccs->cc->module;
case HEAP_BY_DESCR:
- return (get_itbl((StgClosure *)p))->prof.closure_desc;
+ return get_itbl(p)->prof.closure_desc;
case HEAP_BY_TYPE:
- return (get_itbl((StgClosure *)p))->prof.closure_type;
+ return get_itbl(p)->prof.closure_type;
case HEAP_BY_RETAINER:
- return retainerSetOf((StgClosure *)p);
+ // AFAIK, the only closures in the heap which might not have a
+ // valid retainer set are DEAD_WEAK closures.
+ if (isRetainerSetFieldValid(p))
+ return retainerSetOf(p);
+ else
+ return NULL;
+
#else // DEBUG
case HEAP_BY_INFOPTR:
return (void *)((StgClosure *)p)->header.info;
case HEAP_BY_CLOSURE_TYPE:
return type_names[get_itbl(p)->type];
+
#endif
default:
barf("closureIdentity");
return 0;
}
+#ifdef PROFILING
+ if (doingLDVProfiling() && doingRetainerProfiling()) {
+ prog_belch("cannot mix -hb and -hr");
+ stg_exit(1);
+ }
+#endif
+
// we only count eras if we're doing LDV profiling. Otherwise era
// is fixed at zero.
#ifdef PROFILING
return;
}
+ fprintf(fp, "(%d)", ccs->ccsID);
+
// keep printing components of the stack until we run out of space
// in the buffer. If we run out of space, end with "...".
for (; ccs != NULL && ccs != CCS_MAIN; ccs = ccs->prevStack) {
// CAF cost centres print as M.CAF, but we leave the module
// name out of all the others to save space.
if (!strcmp(ccs->cc->label,"CAF")) {
+#ifdef HAVE_SNPRINTF
written = snprintf(buf+next_offset,
(int)max_length-3-(int)next_offset,
"%s.CAF", ccs->cc->module);
+#else
+ written = sprintf(buf+next_offset,
+ "%s.CAF", ccs->cc->module);
+#endif
} else {
if (ccs->prevStack != NULL && ccs->prevStack != CCS_MAIN) {
template = "%s/";
} else {
template = "%s";
}
+#ifdef HAVE_SNPRINTF
written = snprintf(buf+next_offset,
(int)max_length-3-(int)next_offset,
template, ccs->cc->label);
+#else
+ written = sprintf(buf+next_offset,
+ template, ccs->cc->label);
+#endif
}
if (next_offset+written >= max_length-4) {
}
fprintf(fp, "%s", buf);
}
+#endif // PROFILING
-static rtsBool
-str_matches_selector( char* str, char* sel )
+rtsBool
+strMatchesSelector( char* str, char* sel )
{
char* p;
// fprintf(stderr, "str_matches_selector %s %s\n", str, sel);
if (*sel == '\0') return rtsFalse;
}
}
-#endif // PROFILING
/* -----------------------------------------------------------------------------
* Figure out whether a closure should be counted in this census, by
return rtsTrue;
#else
rtsBool b;
- if (RtsFlags.ProfFlags.modSelector) {
- b = str_matches_selector( ((StgClosure *)p)->header.prof.ccs->cc->module,
- RtsFlags.ProfFlags.modSelector );
- if (!b) return rtsFalse;
+
+ // The CCS has a selected field to indicate whether this closure is
+ // deselected by not being mentioned in the module, CC, or CCS
+ // selectors.
+ if (!p->header.prof.ccs->selected) {
+ return rtsFalse;
}
+
if (RtsFlags.ProfFlags.descrSelector) {
- b = str_matches_selector( (get_itbl((StgClosure *)p))->prof.closure_desc,
+ b = strMatchesSelector( (get_itbl((StgClosure *)p))->prof.closure_desc,
RtsFlags.ProfFlags.descrSelector );
if (!b) return rtsFalse;
}
if (RtsFlags.ProfFlags.typeSelector) {
- b = str_matches_selector( (get_itbl((StgClosure *)p))->prof.closure_type,
+ b = strMatchesSelector( (get_itbl((StgClosure *)p))->prof.closure_type,
RtsFlags.ProfFlags.typeSelector );
if (!b) return rtsFalse;
}
- if (RtsFlags.ProfFlags.ccSelector) {
- b = str_matches_selector( ((StgClosure *)p)->header.prof.ccs->cc->label,
- RtsFlags.ProfFlags.ccSelector );
- if (!b) return rtsFalse;
- }
if (RtsFlags.ProfFlags.retainerSelector) {
RetainerSet *rs;
nat i;
rs = retainerSetOf((StgClosure *)p);
if (rs != NULL) {
for (i = 0; i < rs->num; i++) {
- b = str_matches_selector( rs->element[i]->cc->label,
+ b = strMatchesSelector( rs->element[i]->cc->label,
RtsFlags.ProfFlags.retainerSelector );
if (b) return rtsTrue;
}
drag_total += censuses[t].drag_total;
censuses[t].void_total = void_total;
censuses[t].drag_total = drag_total;
- ASSERT( censuses[t].void_total < censuses[t].not_used );
- ASSERT( censuses[t].drag_total < censuses[t].used );
+ ASSERT( censuses[t].void_total <= censuses[t].not_used );
+ ASSERT( censuses[t].drag_total <= censuses[t].used );
}
return;
#ifdef PROFILING
if (RtsFlags.ProfFlags.bioSelector != NULL) {
count = 0;
- if (str_matches_selector("lag", RtsFlags.ProfFlags.bioSelector))
+ if (strMatchesSelector("lag", RtsFlags.ProfFlags.bioSelector))
count += ctr->c.ldv.not_used - ctr->c.ldv.void_total;
- if (str_matches_selector("drag", RtsFlags.ProfFlags.bioSelector))
+ if (strMatchesSelector("drag", RtsFlags.ProfFlags.bioSelector))
count += ctr->c.ldv.drag_total;
- if (str_matches_selector("void", RtsFlags.ProfFlags.bioSelector))
+ if (strMatchesSelector("void", RtsFlags.ProfFlags.bioSelector))
count += ctr->c.ldv.void_total;
- if (str_matches_selector("use", RtsFlags.ProfFlags.bioSelector))
+ if (strMatchesSelector("use", RtsFlags.ProfFlags.bioSelector))
count += ctr->c.ldv.used - ctr->c.ldv.drag_total;
} else
#endif
#ifdef PROFILING
switch (RtsFlags.ProfFlags.doHeapProfile) {
case HEAP_BY_CCS:
- fprint_ccs(hp_file, (CostCentreStack *)ctr->identity, 30);
+ fprint_ccs(hp_file, (CostCentreStack *)ctr->identity, 25);
break;
case HEAP_BY_MOD:
case HEAP_BY_DESCR:
stat_startHeapCensus();
#endif
- // traverse the heap, collecting the census info
+ // Traverse the heap, collecting the census info
+
+ // First the small_alloc_list: we have to fix the free pointer at
+ // the end by calling tidyAllocatedLists() first.
+ tidyAllocateLists();
heapCensusChain( census, small_alloc_list );
+
+ // Now traverse the heap in each generation/step.
if (RtsFlags.GcFlags.generations == 1) {
heapCensusChain( census, g0s0->to_blocks );
} else {