36static int TLSIndex=-1;
46 unsigned curESP,leaveAddr;
62 leaveAddr=p->
Leave(curESP);
63 *(
unsigned *)(curESP)=leaveAddr;
75extern "C" void __declspec(naked) _cdecl _penter(
void)
77 unsigned callerFunc,ESPonReturn,callerRet;
101 mov dword ptr [eax],offset _pleave
112 TlsSetValue(TLSIndex,p);
116 p->
Enter(callerFunc-5,ESPonReturn,callerRet);
130bool ProfileFuncLevelTracer::shuttingDown=
false;
131int ProfileFuncLevelTracer::curFrame=0;
132unsigned ProfileFuncLevelTracer::frameRecordMask;
133bool ProfileFuncLevelTracer::recordCaller=
false;
136 stack(
NULL), usedStack(0), totalStack(0), maxDepth(0)
152 if (usedStack>=totalStack)
163 f->glob.callCount=f->glob.tickPure=f->glob.tickTotal=0;
165 f->cur[i].callCount=f->cur[i].tickPure=f->cur[i].tickTotal=0;
170 StackEntry &s=stack[usedStack++];
179 if (usedStack>=maxDepth)
182 DLOG_GROUP(profile_stack,Debug::RepeatChar(
' ',usedStack-1)
183 << Debug::Hex() <<
this
184 <<
" Enter " << Debug::Width(8) << addr
185 <<
" ESP " << Debug::Width(8) << esp
186 <<
" return " << Debug::Width(8) << ret
187 <<
" level " << Debug::Dec() << usedStack
201 StackEntry &s=stack[usedStack],
202 &sPrev=stack[usedStack-1];
211 if (recordCaller&&usedStack)
212 f->glob.caller.Insert(sPrev.func->addr,1);
218 __int64 delta=cur-s.tickEnter;
220 f->glob.tickTotal+=delta;
223 f->glob.tickPure+=delta-s.tickSubTime;
227 sPrev.tickSubTime+=delta;
232 unsigned mask=frameRecordMask;
237 if (recordCaller&&usedStack>0)
238 f->cur[i].caller.Insert(sPrev.func->addr,1);
239 f->cur[i].callCount++;
241 f->cur[i].tickTotal+=delta;
242 f->cur[i].tickPure+=delta-s.tickSubTime;
260 DCRASH(
"ESP " << Debug::Hex() << esp <<
" does not match " << stack[usedStack].esp << Debug>>Dec());
263 DLOG_GROUP(profile_stack,Debug::RepeatChar(
' ',usedStack-1)
264 << Debug::Hex() <<
this
265 <<
" Leave " << Debug::Width(8) <<
""
266 <<
" ESP " << Debug::Width(8) << stack[usedStack].esp
267 <<
" return " << Debug::Width(8) << stack[usedStack].retVal
268 <<
" level " << Debug::Dec() << usedStack
271 return stack[usedStack].retVal;
279 if (frameRecordMask&(1<<i))
280 for (ProfileFuncLevelTracer *p=head;p;p=p->next)
290 if (!(frameRecordMask&(1<<i)))
295 for (ProfileFuncLevelTracer *p=head;p;p=p->next)
298 for (
int k=0;(f=p->func.Enumerate(k))!=
NULL;k++)
302 p.callCount=p.tickPure=p.tickTotal=0;
306 frameRecordMask|=1<<i;
314 DFAIL_IF(!(frameRecordMask&(1<<which)))
321 frameRecordMask^=1<<which;
324 for (ProfileFuncLevelTracer *p=head;p;p=p->next)
327 for (
int k=0;(f=p->func.Enumerate(k))!=
NULL;k++)
333 f->frame.Append(curFrame,p);
335 f->frame.MixIn(mixIndex,p);
338 p.callCount=p.tickPure=p.tickTotal=0;
347 for (ProfileFuncLevelTracer *p=head;p;p=p->next)
350 for (
int k=0;(f=p->func.Enumerate(k))!=
NULL;k++)
352 f->glob.caller.Clear();
361 e(
NULL), alloc(0), used(0), writeLock(
false)
363 memset(hash,0,
sizeof(hash));
376 memset(hash,0,
sizeof(hash));
379void ProfileFuncLevelTracer::UnsignedMap::_Insert(
unsigned at,
unsigned val,
int countAdd)
387 unsigned delta=unsigned(e);
389 delta=unsigned(e)-delta;
392 for (
unsigned k=0;k<HASH_SIZE;k++)
394 ((
unsigned &)hash[k])+=delta;
397 ((
unsigned &)e[k].next)+=delta;
403 e[used].count=countAdd;
404 e[used].next=hash[at];
410 if (index<0||index>=(
int)used)
417 if (index<0||index>=(
int)used)
419 return e[index].count;
429 memcpy(e,src.e,alloc*
sizeof(Entry));
437 for (
unsigned k=0;k<src.used;k++)
438 Insert(src.e[k].val,src.e[k].count);
443 root(
NULL), tail(&root)
451 List *next=root->next;
460 for (List *p=root;p&&p->frame<frame;p=p->next);
461 return p&&p->frame==frame?&p->p:
NULL;
468 newEntry->frame=frame;
472 tail=&newEntry->next;
478 for (List *oldEntry=root;oldEntry;oldEntry=oldEntry->next)
479 if (oldEntry->frame==frame)
484 oldEntry->p.MixIn(p);
487ProfileFuncLevelTracer::FunctionMap::FunctionMap(
void):
488 e(
NULL), alloc(0), used(0)
490 memset(hash,0,
sizeof(hash));
493ProfileFuncLevelTracer::FunctionMap::~FunctionMap()
497 for (
unsigned k=0;k<used;k++)
499 e[k].funcPtr->~Function();
512 unsigned delta=unsigned(e);
514 delta=unsigned(e)-delta;
517 for (
unsigned k=0;k<HASH_SIZE;k++)
519 ((
unsigned &)hash[k])+=delta;
522 ((
unsigned &)e[k].next)+=delta;
527 unsigned at=(
funcPtr->addr/16)%HASH_SIZE;
529 e[used].next=hash[at];
533ProfileFuncLevelTracer::Function *ProfileFuncLevelTracer::FunctionMap::Enumerate(
int index)
535 if (index<0||index>=(
int)used)
537 return e[index].funcPtr;
545 ProfileFuncLevelTracer::Profile &prof=*(ProfileFuncLevelTracer::Profile *)m_ptr;
564 ProfileFuncLevelTracer::Function *func=(ProfileFuncLevelTracer::Function *)m_funcPtr;
565 if (!func->funcSource)
567 char helpFunc[256],helpFile[256];
571 helpFunc,
sizeof(helpFunc),&ofsFunc,
572 helpFile,
sizeof(helpFile),&func->funcLine,
NULL);
575 wsprintf(help,ofsFunc?
"%s+0x%x":
"%s",helpFunc,ofsFunc);
577 strcpy(func->funcSource,helpFile);
579 strcpy(func->funcName,help);
589 ProfileFuncLevelTracer::Function *func=(ProfileFuncLevelTracer::Function *)m_funcPtr;
590 if (!func->funcSource)
592 return func->funcName;
599 ProfileFuncLevelTracer::Function *func=(ProfileFuncLevelTracer::Function *)m_funcPtr;
607 ProfileFuncLevelTracer::Function *func=(ProfileFuncLevelTracer::Function *)m_funcPtr;
608 if (!func->funcSource)
610 return func->funcLine;
618 ProfileFuncLevelTracer::Function &func=*(ProfileFuncLevelTracer::Function *)m_funcPtr;
623 return func.glob.callCount;
625 ProfileFuncLevelTracer::Profile *prof=func.frame.Find(frame);
635 ProfileFuncLevelTracer::Function &func=*(ProfileFuncLevelTracer::Function *)m_funcPtr;
640 return func.glob.tickTotal;
642 ProfileFuncLevelTracer::Profile *prof=func.frame.Find(frame);
652 ProfileFuncLevelTracer::Function &func=*(ProfileFuncLevelTracer::Function *)m_funcPtr;
657 return func.glob.tickPure;
659 ProfileFuncLevelTracer::Profile *prof=func.frame.Find(frame);
669 ProfileFuncLevelTracer::Function &func=*(ProfileFuncLevelTracer::Function *)m_funcPtr;
675 ret.m_ptr=&func.glob;
678 ProfileFuncLevelTracer::Profile *prof=func.frame.Find(frame);
693 ProfileFuncLevelTracer::Function *f=m_threadID->EnumFunction(index);
719ProfileFuncLevel::ProfileFuncLevel(
void)
780ProfileFuncLevel::ProfileFuncLevel(
void)
786ProfileFuncLevel ProfileFuncLevel::Instance;
787HANDLE ProfileFastCS::testEvent=::CreateEvent(
NULL,
FALSE,
FALSE,
"");
void __declspec(dllexport) CreateDebugDialog(void)
__forceinline void ProfileGetTime(__int64 &t)
void add(float *sum, float *addend)
static void GetSymbol(unsigned addr, char *buf, unsigned bufSize)
Determines symbol for given address.
A function level profile ID.
unsigned GetAddress(void) const
Returns function address.
unsigned _int64 GetFunctionTime(unsigned frame) const
Determine time spend in this function only (exclude any time spend in child functions).
unsigned _int64 GetCalls(unsigned frame) const
Determine call counts.
unsigned GetLine(void) const
Returns the line number for this Id.
unsigned _int64 GetTime(unsigned frame) const
Determine time spend in this function and its children.
const char * GetSource(void) const
Returns the source file this Id is in.
const char * GetFunction(void) const
Returns the function name for this Id.
IdList GetCaller(unsigned frame) const
Determine the list of caller Ids.
A list of function level profile IDs.
bool Enum(unsigned index, Id &id, unsigned *countPtr=0) const
Enumerates the list of IDs.
bool EnumProfile(unsigned index, Id &id) const
Enumerates the list of known function level profile values.
static bool EnumThreads(unsigned index, Thread &thread)
Enumerates the list of known and profiled threads.
void Append(int frame, const Profile &p)
Profile * Find(int frame)
void MixIn(int frame, const Profile &p)
simple unique unsigned/unsigned map
void Copy(const UnsignedMap &src)
unsigned GetCount(int index)
unsigned Enumerate(int index)
void MixIn(const UnsignedMap &src)
static ProfileFuncLevelTracer * GetFirst(void)
static int FrameStart(void)
unsigned Leave(unsigned esp)
~ProfileFuncLevelTracer()
static void FrameEnd(int which, int mixIndex)
Function * FindFunction(unsigned addr)
void Enter(unsigned addr, unsigned esp, unsigned ret)
static void ClearTotals(void)
static void Shutdown(void)
ProfileFuncLevelTracer(void)
#define DLOG_GROUP(group, what)
void ProfileFreeMemory(void *ptr)
void * ProfileReAllocMemory(void *oldPtr, unsigned newSize)
void * ProfileAllocMemory(unsigned numBytes)
function entry (map address -> Function)
int depth
current call depth (for recursion)
unsigned addr
address of this function
char * funcSource
function source
__int64 tickTotal
total time
__int64 callCount
call count
__int64 tickPure
pure time
UnsignedMap caller
caller list
ProfileFuncLevelTracer * tracer
tracer for this profile