#include <IgTools/IgProf/src/IgProfTrace.h>
Public Types | |
typedef uintptr_t | Address |
A value that might be an address, usually memory resource. | |
enum | CounterType { TICK, TICK_PEAK, MAX } |
Counter type. More... | |
typedef unsigned int | RecordType |
Bitmask of properties the record covers. | |
typedef uintmax_t | Value |
A large-sized accumulated value for counters. | |
Public Member Functions | |
IgProfTrace (int opts) | |
Initialise a trace buffer. | |
void | mergeFrom (IgProfTrace &other) |
void | push (void **stack, int depth, Record *recs, int nrecs) |
Push a call frame and its records into the buffer. | |
Stack * | stackRoot (void) const |
~IgProfTrace (void) | |
Static Public Attributes | |
static const RecordType | ACQUIRE = 2 |
static const RecordType | COUNT = 1 |
static const int | MAX_DEPTH = 800 |
Deepest supported stack depth. | |
static const int | OptResources = 1 |
static const int | OptShared = 2 |
static const RecordType | RELEASE = 4 |
Private Member Functions | |
void | acquireResource (Record &rec, Counter *ctr) |
Stack * | childStackNode (Stack *parent, void *address) |
void | debugDump (void) |
bool | findResource (Record &rec, Resource **&rlink, Resource *&res, CounterDef *def) |
IgProfTrace (IgProfTrace &) | |
Counter * | initCounter (Counter *&link, CounterDef *def, Stack *frame) |
void | mergeFrom (int depth, Stack *frame, void **callstack, Record *recs) |
IgProfTrace & | operator= (IgProfTrace &) |
void | releaseResource (Record &rec) |
void | releaseResource (Resource **rlink, Resource *res) |
Static Private Member Functions | |
static void | debugDumpStack (Stack *s, int depth) |
Private Attributes | |
StackCache * | callcache_ |
pthread_mutex_t | mutex_ |
int | options_ |
void ** | poolcur_ |
void ** | poolfirst_ |
Resource * | resfree_ |
Resource ** | restable_ |
Stack * | stack_ |
Classes | |
struct | Counter |
Counter value. More... | |
struct | CounterDef |
Counter definition. More... | |
struct | Record |
Structure used by callers to record values. More... | |
struct | Resource |
Data for a resource. More... | |
struct | Stack |
Stack trace node. More... | |
struct | StackCache |
Structure for call stack cache at the end. More... |
Each trace buffer tracks stack traces and their linked profiling counter values. Optionally the buffer may also account resources linked with the counters: tracking which call stack acquired which yet-unreleased resource and the size of the resource.
The buffer owner is responsible for arranging correct handling of the buffer in presence of multiple threads. Buffers that do not track resources can be made thread-local and access need not be guarded. Resource-accounting buffers must be shared among all the threads able to acquire or release the resource -- the resource records are entered into the buffer in the order of the profile events, but there is no other concept of time and therefore it would not be possible to merge buffers from multiple threads into a canonical time order later on. In the rare situation the resources are thread-local the buffer can be thread-local too, otherwise the caller must ensure atomic access to the buffer.
Technically a trace buffer consists of a header and a collection of fixed-size memory pools for the data, and possibly some pools for hash tables. The stack trace and resource counter information is stored starting in one of the arrays. If the buffer tracks resource information, a resource hash points to resource records. The trace buffer grows by allocating more memory pool as needed.
The stack trace is represented as a tree of nodes keyed by call address. Each stack frame has a singly linked list of children, the addresses called from that stack frame. A frame also has a singly linked list of profiling counters associated with the call tree. Each counter may point to a list of resources known to be live within that buffer; the resources linked with the counter form a singly linked list. The root of the stack trace is a null frame: one with zero call address.
The resource hash table provides quick access to the most recent record on each profiled resource. Each hash bin points to a resource; the resources in the same bin form a singly linked list, a list separate from the singly linked list for resources by counter. A live resource points back to the counter owning that resource, permitting that counter to be decremented when the resource is released.
The memory is allocated and the pool otherwise managed by using raw operating system pritimives: anonymous memory mappings. The buffer avoids calling any non-trivial library calls. The buffer implementation is safe for use in asynchronous signals provided the caller avoids re-enter the same buffer from nested signals.
Definition at line 60 of file IgProfTrace.h.
typedef uintptr_t IgProfTrace::Address |
A value that might be an address, usually memory resource.
Definition at line 74 of file IgProfTrace.h.
typedef unsigned int IgProfTrace::RecordType |
typedef uintmax_t IgProfTrace::Value |
IgProfTrace::IgProfTrace | ( | int | opts | ) |
Initialise a trace buffer.
Definition at line 12 of file IgProfTrace.cc.
References IgProfBuffer::allocateRaw(), IgProfBuffer::allocateSpace(), callcache_, IGPROF_ASSERT, MAX_DEPTH, mutex_, OptResources, OptShared, resfree_, RESOURCE_HASH, restable_, and stack_.
00013 : options_(opts), 00014 restable_(0), 00015 callcache_(0), 00016 resfree_(0), 00017 stack_(0) 00018 { 00019 if (opts & OptShared) 00020 pthread_mutex_init(&mutex_, 0); 00021 00022 // If we are tracking resources, allocate a separate slab of memory 00023 // the resource hash table. This has to be big for large memory 00024 // applications, so it's ok to allocate it separately. Note the 00025 // memory obtained here starts out as zeroed out. 00026 if (opts & OptResources) 00027 restable_ = (Resource **) allocateRaw(RESOURCE_HASH*sizeof(Resource *)); 00028 00029 // Allocate the call cache next. 00030 callcache_ = (StackCache *) allocateSpace(MAX_DEPTH*sizeof(StackCache)); 00031 00032 // Allocate the stack root node. 00033 stack_ = allocate<Stack>(); 00034 00035 // The resource free list starts out empty. 00036 IGPROF_ASSERT(! resfree_); 00037 }
IgProfTrace::~IgProfTrace | ( | void | ) |
Definition at line 39 of file IgProfTrace.cc.
References RESOURCE_HASH, restable_, and IgProfBuffer::unallocateRaw().
00040 { 00041 if (restable_) 00042 unallocateRaw(restable_, RESOURCE_HASH*sizeof(Resource *)); 00043 }
IgProfTrace::IgProfTrace | ( | IgProfTrace & | ) | [private] |
Definition at line 174 of file IgProfTrace.cc.
References IgProfTrace::Record::amount, IgProfTrace::Resource::counter, IgProf::debug(), IgProfTrace::Record::def, IgProfTrace::Resource::def, IgProfTrace::Counter::def, findResource(), IgProfTrace::Counter::frame, IGPROF_ASSERT, IgProfTrace::CounterDef::name, IgProfTrace::Resource::nexthash, IgProfTrace::Resource::nextlive, offset, IgProfTrace::Resource::prevlive, releaseResource(), res, resfree_, IgProfTrace::Record::resource, IgProfTrace::Resource::resource, IgProfTrace::Counter::resources, s, IgProfTrace::Resource::size, and IgHookTrace::symbol().
Referenced by push().
00175 { 00176 IGPROF_ASSERT(ctr); 00177 00178 // Locate the resource in the hash table. 00179 Resource **rlink; 00180 Resource *res = 0; 00181 if (findResource(rec, rlink, res, ctr->def)) 00182 { 00183 IgProf::debug("New %s resource 0x%lx of %ju bytes was never freed in %p\n", 00184 ctr->def->name, rec.resource, res->size, this); 00185 #if IGPROF_DEBUG 00186 int depth = 0; 00187 for (Stack *s = ctr->frame; s; s = s->parent) 00188 { 00189 const char *sym = 0; 00190 const char *lib = 0; 00191 int offset = 0; 00192 int liboffset = 0; 00193 00194 IgHookTrace::symbol(s->address, sym, lib, offset, liboffset); 00195 IgProf::debug (" [%u] %10p %s + %d [%s + %d]\n", ++depth, s->address, 00196 sym ? sym : "?", offset, lib ? lib : "?", liboffset); 00197 } 00198 #endif 00199 00200 // Release the resource, then proceed as if we hadn't found it. 00201 releaseResource(rlink, res); 00202 } 00203 00204 // It wasn't found, insert into the lists as per class documentation. 00205 if ((res = resfree_)) 00206 resfree_ = res->nextlive; 00207 else 00208 res = allocate<Resource>(); 00209 res->resource = rec.resource; 00210 res->size = rec.amount; 00211 res->nexthash = *rlink; 00212 res->prevlive = 0; 00213 res->nextlive = ctr->resources; 00214 res->counter = ctr; 00215 res->def = rec.def; 00216 ctr->resources = *rlink = res; 00217 if (res->nextlive) 00218 res->nextlive->prevlive = res; 00219 }
IgProfTrace::Stack * IgProfTrace::childStackNode | ( | Stack * | parent, | |
void * | address | |||
) | [private] |
Definition at line 46 of file IgProfTrace.cc.
References IgProfTrace::Stack::address, IgProfTrace::Stack::children, IgProfTrace::Stack::counters, k, and IgProfTrace::Stack::sibling.
Referenced by push().
00047 { 00048 // Search for the child's call address in the child stack frames. 00049 Stack **kid = &parent->children; 00050 while (*kid) 00051 { 00052 Stack *k = *kid; 00053 if (k->address == address) 00054 return k; 00055 00056 if ((char *) k->address > (char *) address) 00057 break; 00058 00059 kid = &k->sibling; 00060 } 00061 00062 // Didn't find it, add a new child in address-sorted order. 00063 Stack *next = *kid; 00064 Stack *k = *kid = allocate<Stack>(); 00065 k->address = address; 00066 #if IGPROF_DEBUG 00067 k->parent = parent; 00068 #endif 00069 k->sibling = next; 00070 k->children = 0; 00071 k->counters = 0; 00072 00073 return k; 00074 }
Definition at line 417 of file IgProfTrace.cc.
References callcache_, debugDumpStack(), options_, restable_, and stack_.
00418 { 00419 fprintf (stderr, "TRACE BUFFER %p:\n", this); 00420 fprintf (stderr, " OPTIONS: %d\n", options_); 00421 fprintf (stderr, " RESTABLE: %p\n", restable_); 00422 fprintf (stderr, " CALLCACHE: %p\n", callcache_); 00423 00424 debugDumpStack(stack_, 0); 00425 // debugDumpResources(); 00426 }
Definition at line 392 of file IgProfTrace.cc.
References IgProfTrace::Stack::address, c, IgProfTrace::Stack::children, IgProfTrace::Stack::counters, INDENT, r, and IgProfTrace::Stack::sibling.
Referenced by debugDump().
00393 { 00394 INDENT(2*depth); 00395 fprintf(stderr, "STACK %d frame=%p addr=%p next=%p kids=%p\n", 00396 depth, s, s->address, s->sibling, s->children); 00397 00398 for (Counter *c = s->counters; c; c = c->next) 00399 { 00400 INDENT(2*depth+1); 00401 fprintf(stderr, "COUNTER ctr=%p %s %ju %ju %ju\n", 00402 c, c->def->name, c->ticks, c->value, c->peak); 00403 00404 for (Resource *r = c->resources; r; r = r->nextlive) 00405 { 00406 INDENT(2*depth+2); 00407 fprintf(stderr, "RESOURCE res=%p (prev=%p next=%p) %ju %ju\n", 00408 r, r->prevlive, r->nextlive, r->resource, r->size); 00409 } 00410 } 00411 00412 for (Stack *kid = s->children; kid; kid = kid->sibling) 00413 debugDumpStack(kid, depth+1); 00414 }
bool IgProfTrace::findResource | ( | Record & | rec, | |
Resource **& | rlink, | |||
Resource *& | res, | |||
CounterDef * | def | |||
) | [inline, private] |
Definition at line 92 of file IgProfTrace.cc.
References IgProfBuffer::hash(), r, IgProfTrace::Record::resource, RESOURCE_HASH, and restable_.
Referenced by acquireResource(), and releaseResource().
00096 { 00097 // Locate the resource in the hash table. 00098 rlink = &restable_[hash(rec.resource) & (RESOURCE_HASH-1)]; 00099 00100 while (Resource *r = *rlink) 00101 { 00102 if (r->resource == rec.resource && r->def == def) 00103 { 00104 res = r; 00105 return true; 00106 } 00107 if (r->resource > rec.resource) 00108 return false; 00109 rlink = &r->nexthash; 00110 } 00111 00112 return false; 00113 }
IgProfTrace::Counter * IgProfTrace::initCounter | ( | Counter *& | link, | |
CounterDef * | def, | |||
Stack * | frame | |||
) | [inline, private] |
Definition at line 77 of file IgProfTrace.cc.
References IgProfTrace::Counter::def, IgProfTrace::Counter::frame, IgProfTrace::Counter::next, IgProfTrace::Counter::peak, IgProfTrace::Counter::resources, IgProfTrace::Counter::ticks, and IgProfTrace::Counter::value.
Referenced by push().
00078 { 00079 Counter *ctr = allocate<Counter>(); 00080 ctr->ticks = 0; 00081 ctr->value = 0; 00082 ctr->peak = 0; 00083 ctr->def = def; 00084 ctr->frame = frame; 00085 ctr->next = 0; 00086 ctr->resources = 0; 00087 link = ctr; 00088 return ctr; 00089 }
void IgProfTrace::mergeFrom | ( | int | depth, | |
Stack * | frame, | |||
void ** | callstack, | |||
Record * | recs | |||
) | [private] |
Definition at line 320 of file IgProfTrace.cc.
References ACQUIRE, IgProfTrace::Stack::address, IgProfTrace::Record::amount, c, IgProfTrace::Stack::children, COUNT, IgProfTrace::Stack::counters, IgProfTrace::Record::def, IGPROF_ASSERT, MAX_DEPTH, MERGE_RECS, mergeFrom(), push(), r, RELEASE, IgProfTrace::Record::resource, IgProfTrace::Stack::sibling, TICK_PEAK, IgProfTrace::Record::ticks, and IgProfTrace::Record::type.
00321 { 00322 // Process counters at this call stack level. 00323 int rec = 0; 00324 for (Counter *c = frame->counters; c; c = c->next) 00325 { 00326 if (c->ticks && ! c->resources) 00327 { 00328 if (rec == MERGE_RECS) 00329 { 00330 push(callstack, depth, recs, rec); 00331 rec = 0; 00332 } 00333 00334 recs[rec].type = COUNT; 00335 recs[rec].def = c->def; 00336 recs[rec].amount = c->value; 00337 recs[rec].ticks = c->ticks; 00338 ++rec; 00339 } 00340 else if (c->ticks) 00341 { 00342 for (Resource *r = c->resources; r; r = r->nextlive) 00343 { 00344 if (rec == MERGE_RECS) 00345 { 00346 push(callstack, depth, recs, rec); 00347 rec = 0; 00348 } 00349 00350 recs[rec].type = COUNT | ACQUIRE; 00351 recs[rec].def = c->def; 00352 recs[rec].amount = r->size; 00353 recs[rec].ticks = 1; 00354 recs[rec].resource = r->resource; 00355 ++rec; 00356 } 00357 } 00358 00359 // Adjust the peak counter if necessary. 00360 if (c->def->type == TICK_PEAK && c->peak > c->value) 00361 { 00362 if (rec == MERGE_RECS) 00363 { 00364 push(callstack, depth, recs, rec); 00365 rec = 0; 00366 } 00367 00368 recs[rec].type = COUNT | ACQUIRE | RELEASE; 00369 recs[rec].def = c->def; 00370 recs[rec].amount = c->peak - c->value; 00371 recs[rec].ticks = 1; 00372 recs[rec].resource = ~((Address) 0); 00373 ++rec; 00374 } 00375 } 00376 00377 if (rec) 00378 push(callstack, depth, recs, rec); 00379 00380 // Merge the children. 00381 for (frame = frame->children; frame; frame = frame->sibling) 00382 { 00383 IGPROF_ASSERT(depth < MAX_DEPTH); 00384 callstack[-1] = frame->address; 00385 mergeFrom(depth+1, frame, &callstack[-1], recs); 00386 } 00387 }
void IgProfTrace::mergeFrom | ( | IgProfTrace & | other | ) |
Definition at line 299 of file IgProfTrace.cc.
References IgProfTrace::Stack::address, MAX_DEPTH, MERGE_RECS, mutex_, options_, OptShared, and stack_.
Referenced by IgProf::exitThread(), and mergeFrom().
00300 { 00301 if (options_ & OptShared) 00302 pthread_mutex_lock(&mutex_); 00303 if (other.options_ & OptShared) 00304 pthread_mutex_lock(&other.mutex_); 00305 00306 // Scan stack tree and insert each call stack, including resources. 00307 Record recs[MERGE_RECS]; 00308 void *callstack[MAX_DEPTH+1]; 00309 00310 callstack[MAX_DEPTH] = stack_->address; // null really 00311 mergeFrom(0, other.stack_, &callstack[MAX_DEPTH], recs); 00312 00313 if (other.options_ & OptShared) 00314 pthread_mutex_unlock(&other.mutex_); 00315 if (options_ & OptShared) 00316 pthread_mutex_unlock(&mutex_); 00317 }
IgProfTrace& IgProfTrace::operator= | ( | IgProfTrace & | ) | [private] |
Push a call frame and its records into the buffer.
Definition at line 223 of file IgProfTrace.cc.
References ACQUIRE, acquireResource(), IgProfTrace::StackCache::address, IgProfTrace::Record::amount, c, callcache_, childStackNode(), COUNT, IgProfTrace::Stack::counters, IgProfTrace::Record::def, IgProfTrace::Counter::def, IgProfTrace::StackCache::frame, i, initCounter(), MAX, MAX_DEPTH, mutex_, IgProfTrace::Counter::next, options_, OptShared, IgProfTrace::Counter::peak, RELEASE, releaseResource(), stack_, TICK, TICK_PEAK, IgProfTrace::Record::ticks, IgProfTrace::Counter::ticks, IgProfTrace::CounterDef::type, IgProfTrace::Record::type, TrackValidation_HighPurity_cff::valid, and IgProfTrace::Counter::value.
Referenced by __attribute__(), mergeFrom(), profileSignalHandler(), and remove().
00224 { 00225 if (options_ & OptShared) 00226 pthread_mutex_lock(&mutex_); 00227 00228 // Make sure we operate on non-negative depth. This allows callers 00229 // to do strip off call tree layers without checking for sufficient 00230 // depth themselves. 00231 if (depth < 0) 00232 depth = 0; 00233 00234 // Look up call stack in the cache. 00235 StackCache *cache = callcache_; 00236 Stack *frame = stack_; 00237 00238 for (int i = 0, valid = 1; i < depth && i < MAX_DEPTH; ++i) 00239 { 00240 void *address = stack[depth-i-1]; 00241 if (valid && cache[i].address == address) 00242 frame = cache[i].frame; 00243 else 00244 { 00245 // Look up this call stack child, then cache result. 00246 frame = childStackNode(frame, address); 00247 cache [i].address = address; 00248 cache [i].frame = frame; 00249 valid = 0; 00250 } 00251 } 00252 00253 // OK, we now have our final call stack node. Update its counters 00254 // and the resource allocations as defined by "recs". 00255 for (int i = 0; i < nrecs; ++i) 00256 { 00257 Counter **ctr = 0; 00258 Counter *c = 0; 00259 00260 // If it's a release acquisition or normal tick, update counter. 00261 if (recs[i].type & (COUNT | ACQUIRE)) 00262 { 00263 // Locate the counter. 00264 ctr = &frame->counters; 00265 while (*ctr && (*ctr)->def != recs[i].def) 00266 ctr = &(*ctr)->next; 00267 00268 // If not found, add it. 00269 c = *ctr; 00270 if (! c || c->def != recs[i].def) 00271 c = initCounter(*ctr, recs[i].def, frame); 00272 00273 // Tick the counter. 00274 if (recs[i].def->type == TICK || recs[i].def->type == TICK_PEAK) 00275 c->value += recs[i].amount; 00276 else if (recs[i].def->type == MAX && c->value < recs[i].amount) 00277 c->value = recs[i].amount; 00278 00279 if (recs[i].def->type == TICK_PEAK && c->value > c->peak) 00280 c->peak = c->value; 00281 00282 c->ticks += recs[i].ticks; 00283 } 00284 00285 // Handle resource record for acquisition. 00286 if (recs[i].type & ACQUIRE) 00287 acquireResource(recs[i], c); 00288 00289 // Handle resource record for release. Call stack is empty here. 00290 if (recs[i].type & RELEASE) 00291 releaseResource(recs[i]); 00292 } 00293 00294 if (options_ & OptShared) 00295 pthread_mutex_unlock(&mutex_); 00296 }
Definition at line 160 of file IgProfTrace.cc.
References IgProfTrace::Record::def, findResource(), releaseResource(), and res.
00161 { 00162 // Locate the resource in the hash table. 00163 Resource **rlink; 00164 Resource *res = 0; 00165 if (! findResource(rec, rlink, res, rec.def)) 00166 // Not found, we missed the allocation, ignore this release. 00167 return; 00168 else 00169 // Found, actually release it. 00170 releaseResource(rlink, res); 00171 }
Definition at line 116 of file IgProfTrace.cc.
References IgProfTrace::Resource::counter, IGPROF_ASSERT, IgProfTrace::Resource::nexthash, IgProfTrace::Resource::nextlive, IgProfTrace::Resource::prevlive, resfree_, IgProfTrace::Counter::resources, IgProfTrace::Resource::size, IgProfTrace::Counter::ticks, and IgProfTrace::Counter::value.
Referenced by acquireResource(), push(), and releaseResource().
00117 { 00118 IGPROF_ASSERT(res); 00119 IGPROF_ASSERT(rlink); 00120 IGPROF_ASSERT(res->counter); 00121 IGPROF_ASSERT(res->counter != &FREED); 00122 IGPROF_ASSERT(res->counter->resources); 00123 IGPROF_ASSERT(*rlink == res); 00124 00125 // Deduct the resource from the counter. 00126 Counter *ctr = res->counter; 00127 IGPROF_ASSERT(ctr->value >= res->size); 00128 IGPROF_ASSERT(ctr->ticks > 0); 00129 ctr->value -= res->size; 00130 ctr->ticks--; 00131 00132 // Unchain from hash and counter lists. 00133 *rlink = res->nexthash; 00134 00135 if (Resource *prev = res->prevlive) 00136 { 00137 IGPROF_ASSERT(prev->nextlive == res); 00138 prev->nextlive = res->nextlive; 00139 } 00140 else 00141 { 00142 IGPROF_ASSERT(ctr->resources == res); 00143 ctr->resources = res->nextlive; 00144 } 00145 00146 if (Resource *next = res->nextlive) 00147 { 00148 IGPROF_ASSERT(next->prevlive == res); 00149 next->prevlive = res->prevlive; 00150 } 00151 00152 // Put it on free list. 00153 memset (res, 0, sizeof (*res)); 00154 res->nextlive = resfree_; 00155 res->counter = &FREED; 00156 resfree_ = res; 00157 }
IgProfTrace::Stack * IgProfTrace::stackRoot | ( | void | ) | const [inline] |
Definition at line 217 of file IgProfTrace.h.
References stack_.
Referenced by IgProf::dump().
00218 { return stack_; }
const RecordType IgProfTrace::ACQUIRE = 2 [static] |
Definition at line 160 of file IgProfTrace.h.
Referenced by __attribute__(), mergeFrom(), and push().
StackCache* IgProfTrace::callcache_ [private] |
const RecordType IgProfTrace::COUNT = 1 [static] |
Definition at line 159 of file IgProfTrace.h.
Referenced by __attribute__(), mergeFrom(), profileSignalHandler(), and push().
const int IgProfTrace::MAX_DEPTH = 800 [static] |
Deepest supported stack depth.
Definition at line 71 of file IgProfTrace.h.
Referenced by __attribute__(), IgProfTrace(), mergeFrom(), profileSignalHandler(), and push().
pthread_mutex_t IgProfTrace::mutex_ [private] |
int IgProfTrace::options_ [private] |
const int IgProfTrace::OptResources = 1 [static] |
Definition at line 174 of file IgProfTrace.h.
Referenced by IgProfTrace(), initBuf(), and IgProf::initialize().
const int IgProfTrace::OptShared = 2 [static] |
Definition at line 175 of file IgProfTrace.h.
Referenced by IgProfTrace(), initBuf(), mergeFrom(), and push().
void** IgProfTrace::poolcur_ [private] |
void** IgProfTrace::poolfirst_ [private] |
const RecordType IgProfTrace::RELEASE = 4 [static] |
Resource* IgProfTrace::resfree_ [private] |
Definition at line 205 of file IgProfTrace.h.
Referenced by acquireResource(), IgProfTrace(), and releaseResource().
Resource** IgProfTrace::restable_ [private] |
Definition at line 203 of file IgProfTrace.h.
Referenced by debugDump(), findResource(), IgProfTrace(), and ~IgProfTrace().
Stack* IgProfTrace::stack_ [private] |
Definition at line 206 of file IgProfTrace.h.
Referenced by debugDump(), IgProfTrace(), mergeFrom(), push(), and stackRoot().