/* ** Command & Conquer Generals Zero Hour(tm) ** Copyright 2025 Electronic Arts Inc. ** ** This program is free software: you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation, either version 3 of the License, or ** (at your option) any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program. If not, see . */ /////////////////////////////////////////////////////////////////////////EA-V1 // $File: //depot/GeneralsMD/Staging/code/Libraries/Source/profile/internal_funclevel.h $ // $Author: mhoffe $ // $Revision: #4 $ // $DateTime: 2003/08/14 13:43:29 $ // // ©2003 Electronic Arts // // Function level profiling (internal header) ////////////////////////////////////////////////////////////////////////////// #ifdef _MSC_VER # pragma once #endif #ifndef INTERNAL_FUNCLEVEL_H // Include guard #define INTERNAL_FUNCLEVEL_H class ProfileFuncLevelTracer { friend class ProfileCmdInterface; // can't copy this ProfileFuncLevelTracer(const ProfileFuncLevelTracer&); ProfileFuncLevelTracer& operator=(const ProfileFuncLevelTracer&); public: enum { // # of simultaneous frame recordings MAX_FRAME_RECORDS = 4 }; /// simple unique unsigned/unsigned map class UnsignedMap { UnsignedMap(const UnsignedMap&); UnsignedMap& operator=(const UnsignedMap&); struct Entry { Entry *next; unsigned val; unsigned count; }; enum { // do not make this number too large // a single function uses approx HASH_SIZE*20 bytes! HASH_SIZE = 131 }; Entry *e; unsigned alloc,used; Entry *hash[HASH_SIZE]; bool writeLock; void _Insert(unsigned at, unsigned val, int countAdd); public: UnsignedMap(void); ~UnsignedMap(); void Clear(void); void Insert(unsigned val, int countAdd); unsigned Enumerate(int index); unsigned GetCount(int index); void Copy(const UnsignedMap &src); void MixIn(const UnsignedMap &src); }; /// profile entry struct Profile { /// call count __int64 callCount; /// pure time __int64 tickPure; /// total time __int64 tickTotal; /// caller list UnsignedMap caller; /// tracer for this profile ProfileFuncLevelTracer *tracer; void Copy(const Profile &src) { callCount=src.callCount; tickPure=src.tickPure; tickTotal=src.tickTotal; caller.Copy(src.caller); } void MixIn(const Profile &src) { callCount+=src.callCount; tickPure+=src.tickPure; tickTotal+=src.tickTotal; caller.MixIn(src.caller); } }; /// map of profiles class ProfileMap { ProfileMap(const ProfileMap&); ProfileMap& operator=(const ProfileMap&); struct List { List *next; int frame; Profile p; }; List *root,**tail; public: ProfileMap(void); ~ProfileMap(); Profile *Find(int frame); void Append(int frame, const Profile &p); void MixIn(int frame, const Profile &p); }; /// function entry (map address -> Function) struct Function { /// address of this function unsigned addr; /// global profile Profile glob; /// profile for current frame(s) Profile cur[MAX_FRAME_RECORDS]; /// frame based profiles ProfileMap frame; /// current call depth (for recursion) int depth; /// function source char *funcSource; /// function source line unsigned funcLine; /// function name char *funcName; Function(ProfileFuncLevelTracer *tr) { glob.tracer=tr; for (int k=0;knext) if (e->val==val) { e->count+=countAdd; return; } _Insert(at,val,countAdd); } inline ProfileFuncLevelTracer::Function *ProfileFuncLevelTracer::FunctionMap::Find(unsigned addr) { for (Entry *e=hash[(addr/16)%HASH_SIZE];e;e=e->next) if (e->funcPtr->addr==addr) return e->funcPtr; return NULL; } #endif // INTERNAL_FUNCLEVEL_H