Bug 863429: Fix jprof on debug builds, remove evilness NPOTB DONTBUILD rs=dbaron

This commit is contained in:
Randell Jesup 2013-04-19 09:54:16 -04:00
Родитель 6768e92c6a
Коммит 7852e2c3e4
6 изменённых файлов: 142 добавлений и 105 удалений

Просмотреть файл

@ -100,31 +100,49 @@ static bfd *find_debug_file(bfd *lib, const char *aFileName)
return debugFile; return debugFile;
} }
#define NEXT_SYMBOL \
sp++; \ // Use an indirect array to avoid copying tons of objects
if (sp >= lastSymbol) { \ Symbol ** leaky::ExtendSymbols(int num)
long n = numExternalSymbols + 10000; \ {
externalSymbols = (Symbol*) \ long n = numExternalSymbols + num;
realloc(externalSymbols, (size_t) (sizeof(Symbol) * n)); \
lastSymbol = externalSymbols + n; \ externalSymbols = (Symbol**)
sp = externalSymbols + numExternalSymbols; \ realloc(externalSymbols,
numExternalSymbols = n; \ (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) void leaky::ReadSymbols(const char *aFileName, u_long aBaseAddress)
{ {
int initialSymbols = usefulSymbols; int initialSymbols = usefulSymbols;
if (NULL == externalSymbols) { 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; numExternalSymbols = 10000;
} }
Symbol* sp = externalSymbols + usefulSymbols; Symbol** sp = externalSymbols + usefulSymbols;
Symbol* lastSymbol = externalSymbols + numExternalSymbols; lastSymbol = externalSymbols + numExternalSymbols;
// Create a dummy symbol for the library so, if it doesn't have any // Create a dummy symbol for the library so, if it doesn't have any
// symbols, we show it by library. // symbols, we show it by library.
sp->Init(aFileName, aBaseAddress); (*sp)->Init(aFileName, aBaseAddress);
NEXT_SYMBOL NEXT_SYMBOL;
bfd_boolean kDynamic = (bfd_boolean) false; bfd_boolean kDynamic = (bfd_boolean) false;
@ -188,8 +206,8 @@ void leaky::ReadSymbols(const char *aFileName, u_long aBaseAddress)
if (strncmp("__thunk", nm, 7)) { if (strncmp("__thunk", nm, 7)) {
dnm = cplus_demangle(nm, 1); dnm = cplus_demangle(nm, 1);
} }
sp->Init(dnm ? dnm : nm, syminfo.value + aBaseAddress); (*sp)->Init(dnm ? dnm : nm, syminfo.value + aBaseAddress);
NEXT_SYMBOL NEXT_SYMBOL;
} }
// } // }
} }

Просмотреть файл

@ -4,7 +4,7 @@
#include "intcnt.h" #include "intcnt.h"
IntCount::IntCount() : numInts(0), iPair(0) { } IntCount::IntCount() : numInts(0), iPair(nullptr) { }
IntCount::~IntCount() { delete [] iPair;} IntCount::~IntCount() { delete [] iPair;}
int IntCount::getSize() {return numInts;} int IntCount::getSize() {return numInts;}
int IntCount::getCount(int pos) {return iPair[pos].cnt;} int IntCount::getCount(int pos) {return iPair[pos].cnt;}
@ -50,8 +50,12 @@ int IntCount::countAdd(int index, int increment)
int i; int i;
IntPair *tpair = new IntPair[numInts+1]; IntPair *tpair = new IntPair[numInts+1];
for(i=0; i<divPoint; i++) tpair[i] = iPair[i]; for(i=0; i<divPoint; i++) {
for(i=divPoint; i<numInts; i++) tpair[i+1] = iPair[i]; tpair[i] = iPair[i];
}
for(i=divPoint; i<numInts; i++) {
tpair[i+1] = iPair[i];
}
++numInts; ++numInts;
delete [] iPair; delete [] iPair;
iPair = tpair; iPair = tpair;

Просмотреть файл

@ -17,8 +17,19 @@ public:
int getCount(int pos); int getCount(int pos);
int getIndex(int pos); int getIndex(int pos);
IntCount(const IntCount&old)
{
numInts = old.numInts;
if (numInts > 0) {
iPair = new IntPair[numInts];
for (int i = 0; i < numInts; i++) {
iPair[i] = old.iPair[i];
}
} else {
iPair = nullptr;
}
}
private: private:
IntCount(const IntCount&); // No copy constructor
int numInts; int numInts;
struct IntPair{int idx; int cnt;} *iPair; struct IntPair{int idx; int cnt;} *iPair;

Просмотреть файл

@ -429,6 +429,8 @@ void leaky::open(char *logFile)
{ {
fprintf(outputfd," <a href=\"#thread_%d\">%d</a> ", fprintf(outputfd," <a href=\"#thread_%d\">%d</a> ",
threadArray[i],threadArray[i]); threadArray[i],threadArray[i]);
if ((i+1)%10 == 0)
fprintf(outputfd,"<br>\n");
} }
fprintf(outputfd,"</pre>"); fprintf(outputfd,"</pre>");
} }
@ -453,10 +455,10 @@ void leaky::open(char *logFile)
static int symbolOrder(void const* a, void const* b) static int symbolOrder(void const* a, void const* b)
{ {
Symbol const* ap = (Symbol const *)a; Symbol const** ap = (Symbol const **)a;
Symbol const* bp = (Symbol const *)b; Symbol const** bp = (Symbol const **)b;
return ap->address == bp->address ? 0 : return (*ap)->address == (*bp)->address ? 0 :
(ap->address > bp->address ? 1 : -1); ((*ap)->address > (*bp)->address ? 1 : -1);
} }
void leaky::ReadSharedLibrarySymbols() void leaky::ReadSharedLibrarySymbols()
@ -484,9 +486,9 @@ void leaky::setupSymbols(const char *fileName)
} }
// Now sort them // Now sort them
qsort(externalSymbols, usefulSymbols, sizeof(Symbol), symbolOrder); qsort(externalSymbols, usefulSymbols, sizeof(Symbol *), symbolOrder);
lowestSymbolAddr = externalSymbols[0].address; lowestSymbolAddr = externalSymbols[0]->address;
highestSymbolAddr = externalSymbols[usefulSymbols-1].address; highestSymbolAddr = externalSymbols[usefulSymbols-1]->address;
} }
} }
@ -496,18 +498,18 @@ int leaky::findSymbolIndex(u_long addr)
{ {
u_int base = 0; u_int base = 0;
u_int limit = usefulSymbols - 1; u_int limit = usefulSymbols - 1;
Symbol* end = &externalSymbols[limit]; Symbol** end = &externalSymbols[limit];
while (base <= limit) { while (base <= limit) {
u_int midPoint = (base + limit)>>1; u_int midPoint = (base + limit)>>1;
Symbol* sp = &externalSymbols[midPoint]; Symbol** sp = &externalSymbols[midPoint];
if (addr < sp->address) { if (addr < (*sp)->address) {
if (midPoint == 0) { if (midPoint == 0) {
return -1; return -1;
} }
limit = midPoint - 1; limit = midPoint - 1;
} else { } else {
if (sp+1 < end) { if (sp+1 < end) {
if (addr < (sp+1)->address) { if (addr < (*(sp+1))->address) {
return midPoint; return midPoint;
} }
} else { } else {
@ -526,7 +528,7 @@ Symbol* leaky::findSymbol(u_long addr)
if(idx<0) { if(idx<0) {
return NULL; return NULL;
} else { } 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"); "index", "Count", "Hits", "Function Name");
for(i=0; i<usefulSymbols && countArray[rankingTable[i]]>0; i++) { for(i=0; i<usefulSymbols && countArray[rankingTable[i]]>0; 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 <a name=%d>%8d (%3.1f%%)</a>%s <b>%s</b>\n", fprintf(fp, "%6d %6d (%3.1f%%)%s <a name=%d>%8d (%3.1f%%)</a>%s <b>%s</b>\n",
rankingTable[i], rankingTable[i],
sp->timerHit, (sp->timerHit*1000/totalTimerHits)/10.0, (*sp)->timerHit, ((*sp)->timerHit*1000/totalTimerHits)/10.0,
(sp->timerHit*1000/totalTimerHits)/10.0 >= 10.0 ? "" : " ", ((*sp)->timerHit*1000/totalTimerHits)/10.0 >= 10.0 ? "" : " ",
rankingTable[i], countArray[rankingTable[i]], rankingTable[i], countArray[rankingTable[i]],
(countArray[rankingTable[i]]*1000/totalTimerHits)/10.0, (countArray[rankingTable[i]]*1000/totalTimerHits)/10.0,
(countArray[rankingTable[i]]*1000/totalTimerHits)/10.0 >= 10.0 ? "" : " ", (countArray[rankingTable[i]]*1000/totalTimerHits)/10.0 >= 10.0 ? "" : " ",
symname); symname);
delete [] symname; delete [] symname;
sp->cntC.printReport(fp, this, rankingTable[i], totalTimerHits); (*sp)->cntC.printReport(fp, this, rankingTable[i], totalTimerHits);
fprintf(fp, "<hr>\n"); fprintf(fp, "<hr>\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) { for(mx=usefulSymbols/9, h=581130733; h>0; h/=3) {
if(h<mx) { if(h<mx) {
for(i = h-1; i<usefulSymbols; i++) { for(i = h-1; i<usefulSymbols; i++) {
int j, tmp=rankingTable[i], val = externalSymbols[tmp].timerHit; int j, tmp=rankingTable[i], val = externalSymbols[tmp]->timerHit;
for(j = i; for(j = i;
(j>=h) && (externalSymbols[rankingTable[j-h]].timerHit<val); j-=h) { (j>=h) && (externalSymbols[rankingTable[j-h]]->timerHit<val); j-=h) {
rankingTable[j] = rankingTable[j-h]; rankingTable[j] = rankingTable[j-h];
} }
rankingTable[j] = tmp; rankingTable[j] = tmp;
@ -689,9 +691,9 @@ void leaky::generateReportHTML(FILE *fp, int *countArray, int count, int thread)
// do single-pass and print this out after the loop finishes. // do single-pass and print this out after the loop finishes.
totalTimerHits = 0; totalTimerHits = 0;
for(i=0; for(i=0;
i<usefulSymbols && externalSymbols[rankingTable[i]].timerHit>0; i++) { i<usefulSymbols && externalSymbols[rankingTable[i]]->timerHit>0; i++) {
Symbol *sp=&externalSymbols[rankingTable[i]]; Symbol **sp=&externalSymbols[rankingTable[i]];
totalTimerHits += sp->timerHit; totalTimerHits += (*sp)->timerHit;
} }
if (totalTimerHits == 0) if (totalTimerHits == 0)
totalTimerHits = 1; totalTimerHits = 1;
@ -708,14 +710,14 @@ void leaky::generateReportHTML(FILE *fp, int *countArray, int count, int thread)
fprintf(fp, "Count %%Total Function Name\n"); fprintf(fp, "Count %%Total Function Name\n");
// Now loop for as long as we have timer hits // Now loop for as long as we have timer hits
for(i=0; for(i=0;
i<usefulSymbols && externalSymbols[rankingTable[i]].timerHit>0; i++) { i<usefulSymbols && externalSymbols[rankingTable[i]]->timerHit>0; i++) {
Symbol *sp=&externalSymbols[rankingTable[i]]; Symbol **sp=&externalSymbols[rankingTable[i]];
char *symname = htmlify(sp->name); char *symname = htmlify((*sp)->name);
fprintf(fp, "<a href=\"#%d\">%3d %-2.1f %s</a>\n", fprintf(fp, "<a href=\"#%d\">%3d %-2.1f %s</a>\n",
rankingTable[i], sp->timerHit, rankingTable[i], (*sp)->timerHit,
((float)sp->timerHit/(float)totalTimerHits)*100.0, symname); ((float)(*sp)->timerHit/(float)totalTimerHits)*100.0, symname);
delete [] symname; delete [] symname;
} }
} }
@ -730,8 +732,8 @@ void leaky::analyze(int thread)
// reset hit counts // reset hit counts
for(int i=0; i<usefulSymbols; i++) { for(int i=0; i<usefulSymbols; i++) {
externalSymbols[i].timerHit = 0; externalSymbols[i]->timerHit = 0;
externalSymbols[i].regClear(); externalSymbols[i]->regClear();
} }
// The flag array is used to prevent counting symbols multiple times // The flag array is used to prevent counting symbols multiple times
@ -773,7 +775,7 @@ void leaky::analyze(int thread)
if(idx>=0) { if(idx>=0) {
// Skip over bogus __restore_rt frames that realtime profiling // Skip over bogus __restore_rt frames that realtime profiling
// can introduce. // can introduce.
if (i > 0 && !strcmp(externalSymbols[idx].name, "__restore_rt")) { if (i > 0 && !strcmp(externalSymbols[idx]->name, "__restore_rt")) {
--pcp; --pcp;
--i; --i;
idx = findSymbolIndex(reinterpret_cast<u_long>(*pcp)); idx = findSymbolIndex(reinterpret_cast<u_long>(*pcp));
@ -781,8 +783,8 @@ void leaky::analyze(int thread)
continue; continue;
} }
} }
Symbol *sp=&externalSymbols[idx]; Symbol **sp=&externalSymbols[idx];
char *symname = htmlify(sp->name); char *symname = htmlify((*sp)->name);
fprintf(outputfd,"%c-%s\n",type,symname); fprintf(outputfd,"%c-%s\n",type,symname);
delete [] symname; delete [] symname;
} }
@ -798,7 +800,7 @@ void leaky::analyze(int thread)
if(idx>=0) { if(idx>=0) {
// Skip over bogus __restore_rt frames that realtime profiling // Skip over bogus __restore_rt frames that realtime profiling
// can introduce. // can introduce.
if (i > 0 && !strcmp(externalSymbols[idx].name, "__restore_rt")) { if (i > 0 && !strcmp(externalSymbols[idx]->name, "__restore_rt")) {
--pcp; --pcp;
--i; --i;
idx = findSymbolIndex(reinterpret_cast<u_long>(*pcp)); idx = findSymbolIndex(reinterpret_cast<u_long>(*pcp));
@ -814,8 +816,8 @@ void leaky::analyze(int thread)
// We know who we are and we know who our parrent is. Count this // We know who we are and we know who our parrent is. Count this
if(parrentIdx>=0) { if(parrentIdx>=0) {
externalSymbols[parrentIdx].regChild(idx); externalSymbols[parrentIdx]->regChild(idx);
externalSymbols[idx].regParrent(parrentIdx); externalSymbols[idx]->regParrent(parrentIdx);
} }
// inside if() so an unknown in the middle of a stack won't break // inside if() so an unknown in the middle of a stack won't break
// the link! // 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. // idx should be the function that we were in when we received the signal.
if(idx>=0) { if(idx>=0) {
++externalSymbols[idx].timerHit; ++externalSymbols[idx]->timerHit;
} }
} }

Просмотреть файл

@ -75,7 +75,8 @@ struct leaky {
int stacks; int stacks;
int sfd; int sfd;
Symbol* externalSymbols; Symbol** externalSymbols;
Symbol** lastSymbol;
int usefulSymbols; int usefulSymbols;
int numExternalSymbols; int numExternalSymbols;
StrSet exclusions; StrSet exclusions;
@ -104,13 +105,14 @@ struct leaky {
void displayStackTrace(FILE* out, malloc_log_entry* lep); void displayStackTrace(FILE* out, malloc_log_entry* lep);
Symbol ** ExtendSymbols(int num);
void ReadSymbols(const char* fileName, u_long aBaseAddress); void ReadSymbols(const char* fileName, u_long aBaseAddress);
void ReadSharedLibrarySymbols(); void ReadSharedLibrarySymbols();
void setupSymbols(const char* fileName); void setupSymbols(const char* fileName);
Symbol* findSymbol(u_long address); Symbol* findSymbol(u_long address);
bool excluded(malloc_log_entry* lep); bool excluded(malloc_log_entry* lep);
bool included(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: private:
void generateReportHTML(FILE *fp, int *countArray, int count, int thread); void generateReportHTML(FILE *fp, int *countArray, int count, int thread);

Просмотреть файл

@ -447,7 +447,7 @@ static void startSignalCounter(unsigned long millisec)
} }
} }
static long timerMiliSec = 50; static long timerMilliSec = 50;
#if defined(linux) #if defined(linux)
static int setupRTCSignals(int hz, struct sigaction *sap) static int setupRTCSignals(int hz, struct sigaction *sap)
@ -569,7 +569,7 @@ void *ucontext)
#endif #endif
if (!rtcHz) if (!rtcHz)
startSignalCounter(timerMiliSec); startSignalCounter(timerMilliSec);
} }
NS_EXPORT_(void) setupProfilingStuff(void) NS_EXPORT_(void) setupProfilingStuff(void)
@ -621,12 +621,12 @@ NS_EXPORT_(void) setupProfilingStuff(void)
if(delay) { if(delay) {
double tmp = strtod(delay+strlen("JP_PERIOD="), NULL); double tmp = strtod(delay+strlen("JP_PERIOD="), NULL);
if (tmp>=1e-3) { if (tmp>=1e-3) {
timerMiliSec = static_cast<unsigned long>(1000 * tmp); timerMilliSec = static_cast<unsigned long>(1000 * tmp);
} else { } else {
fprintf(stderr, fprintf(stderr,
"JP_PERIOD of %g less than 0.001 (1ms), using 1ms\n", "JP_PERIOD of %g less than 0.001 (1ms), using 1ms\n",
tmp); tmp);
timerMiliSec = 1; timerMilliSec = 1;
} }
} }
@ -653,7 +653,7 @@ NS_EXPORT_(void) setupProfilingStuff(void)
if (rtc) { if (rtc) {
#if defined(linux) #if defined(linux)
rtcHz = atol(rtc+strlen("JP_RTC_HZ=")); 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. ;) */ realTime = 1; /* It's the _R_TC and all. ;) */
#define IS_POWER_OF_TWO(x) (((x) & ((x) - 1)) == 0) #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 " printf("Jprof: Initialized signal handler and set "
"timer for %lu %s, %d s " "timer for %lu %s, %d s "
"initial delay\n", "initial delay\n",
rtcHz ? rtcHz : timerMiliSec, rtcHz ? rtcHz : timerMilliSec,
rtcHz ? "Hz" : "ms", rtcHz ? "Hz" : "ms",
firstDelay); firstDelay);
@ -771,7 +771,7 @@ NS_EXPORT_(void) setupProfilingStuff(void)
#endif #endif
{ {
puts("Jprof: started timer"); puts("Jprof: started timer");
startSignalCounter(firstDelay*1000 + timerMiliSec); startSignalCounter(firstDelay*1000 + timerMilliSec);
} }
} }
} }