From 7852e2c3e4090220a8214a413850c6d755b632d0 Mon Sep 17 00:00:00 2001 From: Randell Jesup Date: Fri, 19 Apr 2013 09:54:16 -0400 Subject: [PATCH] Bug 863429: Fix jprof on debug builds, remove evilness NPOTB DONTBUILD rs=dbaron --- tools/jprof/bfd.cpp | 60 +++++++++++++++++--------- tools/jprof/intcnt.cpp | 78 ++++++++++++++++++---------------- tools/jprof/intcnt.h | 13 +++++- tools/jprof/leaky.cpp | 76 +++++++++++++++++---------------- tools/jprof/leaky.h | 6 ++- tools/jprof/stub/libmalloc.cpp | 14 +++--- 6 files changed, 142 insertions(+), 105 deletions(-) diff --git a/tools/jprof/bfd.cpp b/tools/jprof/bfd.cpp index 72de7ef09af1..04c770a5a1d9 100644 --- a/tools/jprof/bfd.cpp +++ b/tools/jprof/bfd.cpp @@ -100,31 +100,49 @@ static bfd *find_debug_file(bfd *lib, const char *aFileName) return debugFile; } -#define NEXT_SYMBOL \ - sp++; \ - if (sp >= lastSymbol) { \ - long n = numExternalSymbols + 10000; \ - externalSymbols = (Symbol*) \ - realloc(externalSymbols, (size_t) (sizeof(Symbol) * n)); \ - lastSymbol = externalSymbols + n; \ - sp = externalSymbols + numExternalSymbols; \ - numExternalSymbols = n; \ + +// Use an indirect array to avoid copying tons of objects +Symbol ** leaky::ExtendSymbols(int num) +{ + long n = numExternalSymbols + num; + + externalSymbols = (Symbol**) + realloc(externalSymbols, + (size_t) (sizeof(externalSymbols[0]) * n)); + Symbol *new_array = new Symbol[n]; + for (int i = 0; i < num; i++) { + externalSymbols[i + numExternalSymbols] = &new_array[i]; } + lastSymbol = externalSymbols + n; + Symbol **sp = externalSymbols + numExternalSymbols; + numExternalSymbols = n; + return sp; +} + +#define NEXT_SYMBOL do { sp++; \ + if (sp >= lastSymbol) { \ + sp = ExtendSymbols(16384); \ + } \ + } while (0) void leaky::ReadSymbols(const char *aFileName, u_long aBaseAddress) { int initialSymbols = usefulSymbols; if (NULL == externalSymbols) { - externalSymbols = (Symbol*) malloc(sizeof(Symbol) * 10000); + externalSymbols = (Symbol**) calloc(sizeof(Symbol*),10000); + Symbol *new_array = new Symbol[10000]; + for (int i = 0; i < 10000; i++) { + externalSymbols[i] = &new_array[i]; + } numExternalSymbols = 10000; } - Symbol* sp = externalSymbols + usefulSymbols; - Symbol* lastSymbol = externalSymbols + numExternalSymbols; + Symbol** sp = externalSymbols + usefulSymbols; + lastSymbol = externalSymbols + numExternalSymbols; // Create a dummy symbol for the library so, if it doesn't have any // symbols, we show it by library. - sp->Init(aFileName, aBaseAddress); - NEXT_SYMBOL + (*sp)->Init(aFileName, aBaseAddress); + NEXT_SYMBOL; bfd_boolean kDynamic = (bfd_boolean) false; @@ -184,12 +202,12 @@ void leaky::ReadSymbols(const char *aFileName, u_long aBaseAddress) // if ((syminfo.type == 'T') || (syminfo.type == 't')) { const char* nm = bfd_asymbol_name(sym); if (nm && nm[0]) { - char* dnm = NULL; - if (strncmp("__thunk", nm, 7)) { - dnm = cplus_demangle(nm, 1); - } - sp->Init(dnm ? dnm : nm, syminfo.value + aBaseAddress); - NEXT_SYMBOL + char* dnm = NULL; + if (strncmp("__thunk", nm, 7)) { + dnm = cplus_demangle(nm, 1); + } + (*sp)->Init(dnm ? dnm : nm, syminfo.value + aBaseAddress); + NEXT_SYMBOL; } // } } @@ -199,7 +217,7 @@ void leaky::ReadSymbols(const char *aFileName, u_long aBaseAddress) int interesting = sp - externalSymbols; if (!quiet) { printf("%s provided %d symbols\n", aFileName, - interesting - initialSymbols); + interesting - initialSymbols); } usefulSymbols = interesting; } diff --git a/tools/jprof/intcnt.cpp b/tools/jprof/intcnt.cpp index f6a09b7b1b8f..d0f7e1f33b0e 100644 --- a/tools/jprof/intcnt.cpp +++ b/tools/jprof/intcnt.cpp @@ -4,7 +4,7 @@ #include "intcnt.h" -IntCount::IntCount() : numInts(0), iPair(0) { } +IntCount::IntCount() : numInts(0), iPair(nullptr) { } IntCount::~IntCount() { delete [] iPair;} int IntCount::getSize() {return numInts;} int IntCount::getCount(int pos) {return iPair[pos].cnt;} @@ -19,49 +19,53 @@ void IntCount::clear() int IntCount::countAdd(int index, int increment) { - if(numInts) { - // Do a binary search to find the element - int divPoint = 0; + if(numInts) { + // Do a binary search to find the element + int divPoint = 0; - if(index>iPair[numInts-1].idx) { + if(index>iPair[numInts-1].idx) { divPoint = numInts; - } else if(indexiPair[mid].idx) { - if(midiPair[mid].idx) { + if(mid 0) { + iPair = new IntPair[numInts]; + for (int i = 0; i < numInts; i++) { + iPair[i] = old.iPair[i]; + } + } else { + iPair = nullptr; + } + } private: - IntCount(const IntCount&); // No copy constructor int numInts; struct IntPair{int idx; int cnt;} *iPair; diff --git a/tools/jprof/leaky.cpp b/tools/jprof/leaky.cpp index 4385551937f3..f3244a69061c 100644 --- a/tools/jprof/leaky.cpp +++ b/tools/jprof/leaky.cpp @@ -429,6 +429,8 @@ void leaky::open(char *logFile) { fprintf(outputfd," %d ", threadArray[i],threadArray[i]); + if ((i+1)%10 == 0) + fprintf(outputfd,"
\n"); } fprintf(outputfd,""); } @@ -453,10 +455,10 @@ void leaky::open(char *logFile) static int symbolOrder(void const* a, void const* b) { - Symbol const* ap = (Symbol const *)a; - Symbol const* bp = (Symbol const *)b; - return ap->address == bp->address ? 0 : - (ap->address > bp->address ? 1 : -1); + Symbol const** ap = (Symbol const **)a; + Symbol const** bp = (Symbol const **)b; + return (*ap)->address == (*bp)->address ? 0 : + ((*ap)->address > (*bp)->address ? 1 : -1); } void leaky::ReadSharedLibrarySymbols() @@ -484,9 +486,9 @@ void leaky::setupSymbols(const char *fileName) } // Now sort them - qsort(externalSymbols, usefulSymbols, sizeof(Symbol), symbolOrder); - lowestSymbolAddr = externalSymbols[0].address; - highestSymbolAddr = externalSymbols[usefulSymbols-1].address; + qsort(externalSymbols, usefulSymbols, sizeof(Symbol *), symbolOrder); + lowestSymbolAddr = externalSymbols[0]->address; + highestSymbolAddr = externalSymbols[usefulSymbols-1]->address; } } @@ -496,18 +498,18 @@ int leaky::findSymbolIndex(u_long addr) { u_int base = 0; u_int limit = usefulSymbols - 1; - Symbol* end = &externalSymbols[limit]; + Symbol** end = &externalSymbols[limit]; while (base <= limit) { u_int midPoint = (base + limit)>>1; - Symbol* sp = &externalSymbols[midPoint]; - if (addr < sp->address) { + Symbol** sp = &externalSymbols[midPoint]; + if (addr < (*sp)->address) { if (midPoint == 0) { return -1; } limit = midPoint - 1; } else { if (sp+1 < end) { - if (addr < (sp+1)->address) { + if (addr < (*(sp+1))->address) { return midPoint; } } else { @@ -526,7 +528,7 @@ Symbol* leaky::findSymbol(u_long addr) if(idx<0) { return NULL; } else { - return &externalSymbols[idx]; + return externalSymbols[idx]; } } @@ -644,22 +646,22 @@ void leaky::generateReportHTML(FILE *fp, int *countArray, int count, int thread) "index", "Count", "Hits", "Function Name"); for(i=0; i0; i++) { - Symbol *sp=&externalSymbols[rankingTable[i]]; + Symbol **sp=&externalSymbols[rankingTable[i]]; - sp->cntP.printReport(fp, this, rankingTable[i], totalTimerHits); + (*sp)->cntP.printReport(fp, this, rankingTable[i], totalTimerHits); - char *symname = htmlify(sp->name); + char *symname = htmlify((*sp)->name); fprintf(fp, "%6d %6d (%3.1f%%)%s %8d (%3.1f%%)%s %s\n", rankingTable[i], - sp->timerHit, (sp->timerHit*1000/totalTimerHits)/10.0, - (sp->timerHit*1000/totalTimerHits)/10.0 >= 10.0 ? "" : " ", + (*sp)->timerHit, ((*sp)->timerHit*1000/totalTimerHits)/10.0, + ((*sp)->timerHit*1000/totalTimerHits)/10.0 >= 10.0 ? "" : " ", rankingTable[i], countArray[rankingTable[i]], (countArray[rankingTable[i]]*1000/totalTimerHits)/10.0, (countArray[rankingTable[i]]*1000/totalTimerHits)/10.0 >= 10.0 ? "" : " ", symname); delete [] symname; - sp->cntC.printReport(fp, this, rankingTable[i], totalTimerHits); + (*sp)->cntC.printReport(fp, this, rankingTable[i], totalTimerHits); fprintf(fp, "
\n"); } @@ -673,9 +675,9 @@ void leaky::generateReportHTML(FILE *fp, int *countArray, int count, int thread) for(mx=usefulSymbols/9, h=581130733; h>0; h/=3) { if(htimerHit; for(j = i; - (j>=h) && (externalSymbols[rankingTable[j-h]].timerHit=h) && (externalSymbols[rankingTable[j-h]]->timerHit0; i++) { - Symbol *sp=&externalSymbols[rankingTable[i]]; - totalTimerHits += sp->timerHit; + itimerHit>0; i++) { + Symbol **sp=&externalSymbols[rankingTable[i]]; + totalTimerHits += (*sp)->timerHit; } if (totalTimerHits == 0) totalTimerHits = 1; @@ -708,14 +710,14 @@ void leaky::generateReportHTML(FILE *fp, int *countArray, int count, int thread) fprintf(fp, "Count %%Total Function Name\n"); // Now loop for as long as we have timer hits for(i=0; - i0; i++) { + itimerHit>0; i++) { - Symbol *sp=&externalSymbols[rankingTable[i]]; + Symbol **sp=&externalSymbols[rankingTable[i]]; - char *symname = htmlify(sp->name); + char *symname = htmlify((*sp)->name); fprintf(fp, "%3d %-2.1f %s\n", - rankingTable[i], sp->timerHit, - ((float)sp->timerHit/(float)totalTimerHits)*100.0, symname); + rankingTable[i], (*sp)->timerHit, + ((float)(*sp)->timerHit/(float)totalTimerHits)*100.0, symname); delete [] symname; } } @@ -730,8 +732,8 @@ void leaky::analyze(int thread) // reset hit counts for(int i=0; itimerHit = 0; + externalSymbols[i]->regClear(); } // The flag array is used to prevent counting symbols multiple times @@ -773,7 +775,7 @@ void leaky::analyze(int thread) if(idx>=0) { // Skip over bogus __restore_rt frames that realtime profiling // can introduce. - if (i > 0 && !strcmp(externalSymbols[idx].name, "__restore_rt")) { + if (i > 0 && !strcmp(externalSymbols[idx]->name, "__restore_rt")) { --pcp; --i; idx = findSymbolIndex(reinterpret_cast(*pcp)); @@ -781,8 +783,8 @@ void leaky::analyze(int thread) continue; } } - Symbol *sp=&externalSymbols[idx]; - char *symname = htmlify(sp->name); + Symbol **sp=&externalSymbols[idx]; + char *symname = htmlify((*sp)->name); fprintf(outputfd,"%c-%s\n",type,symname); delete [] symname; } @@ -798,7 +800,7 @@ void leaky::analyze(int thread) if(idx>=0) { // Skip over bogus __restore_rt frames that realtime profiling // can introduce. - if (i > 0 && !strcmp(externalSymbols[idx].name, "__restore_rt")) { + if (i > 0 && !strcmp(externalSymbols[idx]->name, "__restore_rt")) { --pcp; --i; idx = findSymbolIndex(reinterpret_cast(*pcp)); @@ -814,8 +816,8 @@ void leaky::analyze(int thread) // We know who we are and we know who our parrent is. Count this if(parrentIdx>=0) { - externalSymbols[parrentIdx].regChild(idx); - externalSymbols[idx].regParrent(parrentIdx); + externalSymbols[parrentIdx]->regChild(idx); + externalSymbols[idx]->regParrent(parrentIdx); } // inside if() so an unknown in the middle of a stack won't break // the link! @@ -825,7 +827,7 @@ void leaky::analyze(int thread) // idx should be the function that we were in when we received the signal. if(idx>=0) { - ++externalSymbols[idx].timerHit; + ++externalSymbols[idx]->timerHit; } } diff --git a/tools/jprof/leaky.h b/tools/jprof/leaky.h index 0bbbed35db17..5dafe30b920a 100644 --- a/tools/jprof/leaky.h +++ b/tools/jprof/leaky.h @@ -75,7 +75,8 @@ struct leaky { int stacks; int sfd; - Symbol* externalSymbols; + Symbol** externalSymbols; + Symbol** lastSymbol; int usefulSymbols; int numExternalSymbols; StrSet exclusions; @@ -104,13 +105,14 @@ struct leaky { void displayStackTrace(FILE* out, malloc_log_entry* lep); + Symbol ** ExtendSymbols(int num); void ReadSymbols(const char* fileName, u_long aBaseAddress); void ReadSharedLibrarySymbols(); void setupSymbols(const char* fileName); Symbol* findSymbol(u_long address); bool excluded(malloc_log_entry* lep); bool included(malloc_log_entry* lep); - const char* indexToName(int idx) {return externalSymbols[idx].name;} + const char* indexToName(int idx) {return externalSymbols[idx]->name;} private: void generateReportHTML(FILE *fp, int *countArray, int count, int thread); diff --git a/tools/jprof/stub/libmalloc.cpp b/tools/jprof/stub/libmalloc.cpp index 00ec2e540a3e..ea74941f2288 100644 --- a/tools/jprof/stub/libmalloc.cpp +++ b/tools/jprof/stub/libmalloc.cpp @@ -447,7 +447,7 @@ static void startSignalCounter(unsigned long millisec) } } -static long timerMiliSec = 50; +static long timerMilliSec = 50; #if defined(linux) static int setupRTCSignals(int hz, struct sigaction *sap) @@ -569,7 +569,7 @@ void *ucontext) #endif if (!rtcHz) - startSignalCounter(timerMiliSec); + startSignalCounter(timerMilliSec); } NS_EXPORT_(void) setupProfilingStuff(void) @@ -621,12 +621,12 @@ NS_EXPORT_(void) setupProfilingStuff(void) if(delay) { double tmp = strtod(delay+strlen("JP_PERIOD="), NULL); if (tmp>=1e-3) { - timerMiliSec = static_cast(1000 * tmp); + timerMilliSec = static_cast(1000 * tmp); } else { fprintf(stderr, "JP_PERIOD of %g less than 0.001 (1ms), using 1ms\n", tmp); - timerMiliSec = 1; + timerMilliSec = 1; } } @@ -653,7 +653,7 @@ NS_EXPORT_(void) setupProfilingStuff(void) if (rtc) { #if defined(linux) rtcHz = atol(rtc+strlen("JP_RTC_HZ=")); - timerMiliSec = 0; /* This makes JP_FIRST work right. */ + timerMilliSec = 0; /* This makes JP_FIRST work right. */ realTime = 1; /* It's the _R_TC and all. ;) */ #define IS_POWER_OF_TWO(x) (((x) & ((x) - 1)) == 0) @@ -754,7 +754,7 @@ NS_EXPORT_(void) setupProfilingStuff(void) printf("Jprof: Initialized signal handler and set " "timer for %lu %s, %d s " "initial delay\n", - rtcHz ? rtcHz : timerMiliSec, + rtcHz ? rtcHz : timerMilliSec, rtcHz ? "Hz" : "ms", firstDelay); @@ -771,7 +771,7 @@ NS_EXPORT_(void) setupProfilingStuff(void) #endif { puts("Jprof: started timer"); - startSignalCounter(firstDelay*1000 + timerMiliSec); + startSignalCounter(firstDelay*1000 + timerMilliSec); } } }