internal_funclevel.h 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362
  1. /*
  2. ** Command & Conquer Generals Zero Hour(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /////////////////////////////////////////////////////////////////////////EA-V1
  19. // $File: //depot/GeneralsMD/Staging/code/Libraries/Source/profile/internal_funclevel.h $
  20. // $Author: mhoffe $
  21. // $Revision: #4 $
  22. // $DateTime: 2003/08/14 13:43:29 $
  23. //
  24. // ©2003 Electronic Arts
  25. //
  26. // Function level profiling (internal header)
  27. //////////////////////////////////////////////////////////////////////////////
  28. #ifdef _MSC_VER
  29. # pragma once
  30. #endif
  31. #ifndef INTERNAL_FUNCLEVEL_H // Include guard
  32. #define INTERNAL_FUNCLEVEL_H
  33. class ProfileFuncLevelTracer
  34. {
  35. friend class ProfileCmdInterface;
  36. // can't copy this
  37. ProfileFuncLevelTracer(const ProfileFuncLevelTracer&);
  38. ProfileFuncLevelTracer& operator=(const ProfileFuncLevelTracer&);
  39. public:
  40. enum
  41. {
  42. // # of simultaneous frame recordings
  43. MAX_FRAME_RECORDS = 4
  44. };
  45. /// simple unique unsigned/unsigned map
  46. class UnsignedMap
  47. {
  48. UnsignedMap(const UnsignedMap&);
  49. UnsignedMap& operator=(const UnsignedMap&);
  50. struct Entry
  51. {
  52. Entry *next;
  53. unsigned val;
  54. unsigned count;
  55. };
  56. enum
  57. {
  58. // do not make this number too large
  59. // a single function uses approx HASH_SIZE*20 bytes!
  60. HASH_SIZE = 131
  61. };
  62. Entry *e;
  63. unsigned alloc,used;
  64. Entry *hash[HASH_SIZE];
  65. bool writeLock;
  66. void _Insert(unsigned at, unsigned val, int countAdd);
  67. public:
  68. UnsignedMap(void);
  69. ~UnsignedMap();
  70. void Clear(void);
  71. void Insert(unsigned val, int countAdd);
  72. unsigned Enumerate(int index);
  73. unsigned GetCount(int index);
  74. void Copy(const UnsignedMap &src);
  75. void MixIn(const UnsignedMap &src);
  76. };
  77. /// profile entry
  78. struct Profile
  79. {
  80. /// call count
  81. __int64 callCount;
  82. /// pure time
  83. __int64 tickPure;
  84. /// total time
  85. __int64 tickTotal;
  86. /// caller list
  87. UnsignedMap caller;
  88. /// tracer for this profile
  89. ProfileFuncLevelTracer *tracer;
  90. void Copy(const Profile &src)
  91. {
  92. callCount=src.callCount;
  93. tickPure=src.tickPure;
  94. tickTotal=src.tickTotal;
  95. caller.Copy(src.caller);
  96. }
  97. void MixIn(const Profile &src)
  98. {
  99. callCount+=src.callCount;
  100. tickPure+=src.tickPure;
  101. tickTotal+=src.tickTotal;
  102. caller.MixIn(src.caller);
  103. }
  104. };
  105. /// map of profiles
  106. class ProfileMap
  107. {
  108. ProfileMap(const ProfileMap&);
  109. ProfileMap& operator=(const ProfileMap&);
  110. struct List
  111. {
  112. List *next;
  113. int frame;
  114. Profile p;
  115. };
  116. List *root,**tail;
  117. public:
  118. ProfileMap(void);
  119. ~ProfileMap();
  120. Profile *Find(int frame);
  121. void Append(int frame, const Profile &p);
  122. void MixIn(int frame, const Profile &p);
  123. };
  124. /// function entry (map address -> Function)
  125. struct Function
  126. {
  127. /// address of this function
  128. unsigned addr;
  129. /// global profile
  130. Profile glob;
  131. /// profile for current frame(s)
  132. Profile cur[MAX_FRAME_RECORDS];
  133. /// frame based profiles
  134. ProfileMap frame;
  135. /// current call depth (for recursion)
  136. int depth;
  137. /// function source
  138. char *funcSource;
  139. /// function source line
  140. unsigned funcLine;
  141. /// function name
  142. char *funcName;
  143. Function(ProfileFuncLevelTracer *tr)
  144. {
  145. glob.tracer=tr;
  146. for (int k=0;k<MAX_FRAME_RECORDS;k++)
  147. cur[k].tracer=tr;
  148. funcSource=funcName=NULL;
  149. funcLine=0;
  150. }
  151. };
  152. ProfileFuncLevelTracer(void);
  153. ~ProfileFuncLevelTracer();
  154. /**
  155. Enters the function at the given address.
  156. @param addr function address
  157. @param esp current ESP value
  158. @param ret return address for given function
  159. */
  160. void Enter(unsigned addr, unsigned esp, unsigned ret);
  161. /**
  162. Leaves the function at the ESP value.
  163. If this does not match with the last Enter call
  164. the internal stack is unwound until a match is found.
  165. @param esp current ESP value
  166. @return return address
  167. */
  168. unsigned Leave(unsigned esp);
  169. /**
  170. Shutdown function.
  171. */
  172. static void Shutdown(void);
  173. /**
  174. Starts frame based profiling, starts a new frame.
  175. */
  176. static int FrameStart(void);
  177. /**
  178. Ends frame based profiling.
  179. */
  180. static void FrameEnd(int which, int mixIndex);
  181. /**
  182. Clears all total values.
  183. */
  184. static void ClearTotals(void);
  185. /**
  186. Retrieves the first function level tracer.
  187. \return first function level tracer
  188. */
  189. static ProfileFuncLevelTracer *GetFirst(void)
  190. {
  191. return head;
  192. }
  193. /**
  194. Retrieves next function level tracer.
  195. \return next function level tracer, NULL if none
  196. */
  197. ProfileFuncLevelTracer *GetNext(void)
  198. {
  199. return next;
  200. }
  201. Function *FindFunction(unsigned addr)
  202. {
  203. return func.Find(addr);
  204. }
  205. Function *EnumFunction(unsigned index)
  206. {
  207. return func.Enumerate(index);
  208. }
  209. private:
  210. /// single stack entry
  211. struct StackEntry
  212. {
  213. /// function
  214. Function *func;
  215. /// ESP value
  216. unsigned esp;
  217. /// return value
  218. unsigned retVal;
  219. /// enter tick count
  220. __int64 tickEnter;
  221. /// time spend in called functions
  222. __int64 tickSubTime;
  223. };
  224. /// map of functions
  225. class FunctionMap
  226. {
  227. FunctionMap(const FunctionMap&);
  228. FunctionMap& operator=(const FunctionMap&);
  229. struct Entry
  230. {
  231. Entry *next;
  232. Function *funcPtr;
  233. };
  234. enum
  235. {
  236. HASH_SIZE = 15551
  237. };
  238. Entry *e;
  239. unsigned alloc,used;
  240. Entry *hash[HASH_SIZE];
  241. public:
  242. FunctionMap(void);
  243. ~FunctionMap();
  244. Function *Find(unsigned addr);
  245. void Insert(Function *funcPtr);
  246. Function *Enumerate(int index);
  247. };
  248. /// head of list
  249. static ProfileFuncLevelTracer *head;
  250. /// next tracer object
  251. ProfileFuncLevelTracer *next;
  252. /// are we in shutdown mode?
  253. static bool shuttingDown;
  254. /// stack
  255. StackEntry *stack;
  256. /// number of used entries
  257. int usedStack;
  258. /// total number of entries
  259. int totalStack;
  260. /// max call depth
  261. int maxDepth;
  262. /// current frame
  263. static int curFrame;
  264. /// function map
  265. FunctionMap func;
  266. /// bit mask, currently recording which cur[] entries?
  267. static unsigned frameRecordMask;
  268. /// record caller information?
  269. static bool recordCaller;
  270. };
  271. inline void ProfileFuncLevelTracer::UnsignedMap::Insert(unsigned val, int countAdd)
  272. {
  273. // in hash?
  274. unsigned at=(val/16)%HASH_SIZE;
  275. for (Entry *e=hash[at];e;e=e->next)
  276. if (e->val==val)
  277. {
  278. e->count+=countAdd;
  279. return;
  280. }
  281. _Insert(at,val,countAdd);
  282. }
  283. inline ProfileFuncLevelTracer::Function *ProfileFuncLevelTracer::FunctionMap::Find(unsigned addr)
  284. {
  285. for (Entry *e=hash[(addr/16)%HASH_SIZE];e;e=e->next)
  286. if (e->funcPtr->addr==addr)
  287. return e->funcPtr;
  288. return NULL;
  289. }
  290. #endif // INTERNAL_FUNCLEVEL_H