static void Stop(ProfilerObject *pObj, ProfilerContext *self, ProfilerEntry *entry) { PY_LONG_LONG tt = CALL_TIMER(pObj) - self->t0; PY_LONG_LONG it = tt - self->subt; if (self->previous) self->previous->subt += tt; pObj->currentProfilerContext = self->previous; if (--entry->recursionLevel == 0) entry->tt += tt; else ++entry->recursivecallcount; entry->it += it; entry->callcount++; if ((pObj->flags & POF_SUBCALLS) && self->previous) { /* find or create an entry for me in my caller's entry */ ProfilerEntry *caller = self->previous->ctxEntry; ProfilerSubEntry *subentry = getSubEntry(pObj, caller, entry); if (subentry) { if (--subentry->recursionLevel == 0) subentry->tt += tt; else ++subentry->recursivecallcount; subentry->it += it; ++subentry->callcount; } } }
static void initContext(ProfilerObject *pObj, ProfilerContext *self, ProfilerEntry *entry) { self->ctxEntry = entry; self->subt = 0; self->previous = pObj->currentProfilerContext; pObj->currentProfilerContext = self; ++entry->recursionLevel; if ((pObj->flags & POF_SUBCALLS) && self->previous) { /* find or create an entry for me in my caller's entry */ ProfilerEntry *caller = self->previous->ctxEntry; ProfilerSubEntry *subentry = getSubEntry(pObj, caller, entry); if (subentry == NULL) subentry = newSubEntry(pObj, caller, entry); if (subentry) ++subentry->recursionLevel; } self->t0 = CALL_TIMER(pObj); }
static int profiler_callback(PyObject *self, PyFrameObject *frame, int what, PyObject *arg) { ProfilerObject *pObj = (ProfilerObject*)self; { /* keep error state, see ptrace_enter_call above. * We could keep this more focused, only really needed * when calling a user time function, and initializing * a user object */ PyObject *et, *ev, *tb; PyErr_Fetch(&et, &ev, &tb); pObj->currentTime = CALL_TIMER(pObj); SelectStack(pObj); PyErr_Restore(et, ev, tb); } if (pObj->currentProfilerStack == NULL) return 0; switch (what) { /* the 'frame' of a called function is about to start its execution */ case PyTrace_CALL: ptrace_enter_call(self, (void *)frame->f_code, (PyObject *)frame->f_code); break; /* the 'frame' of a called function is about to finish (either normally or with an exception) */ case PyTrace_RETURN: ptrace_leave_call(self, (void *)frame->f_code); break; /* case PyTrace_EXCEPTION: If the exception results in the function exiting, a PyTrace_RETURN event will be generated, so we don't need to handle it. */ #ifdef PyTrace_C_CALL /* not defined in Python <= 2.3 */ /* the Python function 'frame' is issuing a call to the built-in function 'arg' */ case PyTrace_C_CALL: if ((((ProfilerObject *)self)->flags & POF_BUILTINS) && PyCFunction_Check(arg)) { ptrace_enter_call(self, ((PyCFunctionObject *)arg)->m_ml, arg); } break; /* the call to the built-in function 'arg' is returning into its caller 'frame' */ case PyTrace_C_RETURN: /* ...normally */ case PyTrace_C_EXCEPTION: /* ...with an exception set */ if ((((ProfilerObject *)self)->flags & POF_BUILTINS) && PyCFunction_Check(arg)) { ptrace_leave_call(self, ((PyCFunctionObject *)arg)->m_ml); } break; #endif default: break; } return 0; }