17db96d56Sopenharmony_ci#ifndef Py_BUILD_CORE_BUILTIN 27db96d56Sopenharmony_ci# define Py_BUILD_CORE_MODULE 1 37db96d56Sopenharmony_ci#endif 47db96d56Sopenharmony_ci 57db96d56Sopenharmony_ci#include "Python.h" 67db96d56Sopenharmony_ci#include "pycore_call.h" // _PyObject_CallNoArgs() 77db96d56Sopenharmony_ci#include "pycore_pystate.h" // _PyThreadState_GET() 87db96d56Sopenharmony_ci#include "rotatingtree.h" 97db96d56Sopenharmony_ci 107db96d56Sopenharmony_ci/************************************************************/ 117db96d56Sopenharmony_ci/* Written by Brett Rosen and Ted Czotter */ 127db96d56Sopenharmony_ci 137db96d56Sopenharmony_cistruct _ProfilerEntry; 147db96d56Sopenharmony_ci 157db96d56Sopenharmony_ci/* represents a function called from another function */ 167db96d56Sopenharmony_citypedef struct _ProfilerSubEntry { 177db96d56Sopenharmony_ci rotating_node_t header; 187db96d56Sopenharmony_ci _PyTime_t tt; 197db96d56Sopenharmony_ci _PyTime_t it; 207db96d56Sopenharmony_ci long callcount; 217db96d56Sopenharmony_ci long recursivecallcount; 227db96d56Sopenharmony_ci long recursionLevel; 237db96d56Sopenharmony_ci} ProfilerSubEntry; 247db96d56Sopenharmony_ci 257db96d56Sopenharmony_ci/* represents a function or user defined block */ 267db96d56Sopenharmony_citypedef struct _ProfilerEntry { 277db96d56Sopenharmony_ci rotating_node_t header; 287db96d56Sopenharmony_ci PyObject *userObj; /* PyCodeObject, or a descriptive str for builtins */ 297db96d56Sopenharmony_ci _PyTime_t tt; /* total time in this entry */ 307db96d56Sopenharmony_ci _PyTime_t it; /* inline time in this entry (not in subcalls) */ 317db96d56Sopenharmony_ci long callcount; /* how many times this was called */ 327db96d56Sopenharmony_ci long recursivecallcount; /* how many times called recursively */ 337db96d56Sopenharmony_ci long recursionLevel; 347db96d56Sopenharmony_ci rotating_node_t *calls; 357db96d56Sopenharmony_ci} ProfilerEntry; 367db96d56Sopenharmony_ci 377db96d56Sopenharmony_citypedef struct _ProfilerContext { 387db96d56Sopenharmony_ci _PyTime_t t0; 397db96d56Sopenharmony_ci _PyTime_t subt; 407db96d56Sopenharmony_ci struct _ProfilerContext *previous; 417db96d56Sopenharmony_ci ProfilerEntry *ctxEntry; 427db96d56Sopenharmony_ci} ProfilerContext; 437db96d56Sopenharmony_ci 447db96d56Sopenharmony_citypedef struct { 457db96d56Sopenharmony_ci PyObject_HEAD 467db96d56Sopenharmony_ci rotating_node_t *profilerEntries; 477db96d56Sopenharmony_ci ProfilerContext *currentProfilerContext; 487db96d56Sopenharmony_ci ProfilerContext *freelistProfilerContext; 497db96d56Sopenharmony_ci int flags; 507db96d56Sopenharmony_ci PyObject *externalTimer; 517db96d56Sopenharmony_ci double externalTimerUnit; 527db96d56Sopenharmony_ci} ProfilerObject; 537db96d56Sopenharmony_ci 547db96d56Sopenharmony_ci#define POF_ENABLED 0x001 557db96d56Sopenharmony_ci#define POF_SUBCALLS 0x002 567db96d56Sopenharmony_ci#define POF_BUILTINS 0x004 577db96d56Sopenharmony_ci#define POF_NOMEMORY 0x100 587db96d56Sopenharmony_ci 597db96d56Sopenharmony_ci/*[clinic input] 607db96d56Sopenharmony_cimodule _lsprof 617db96d56Sopenharmony_ciclass _lsprof.Profiler "ProfilerObject *" "&ProfilerType" 627db96d56Sopenharmony_ci[clinic start generated code]*/ 637db96d56Sopenharmony_ci/*[clinic end generated code: output=da39a3ee5e6b4b0d input=e349ac952152f336]*/ 647db96d56Sopenharmony_ci 657db96d56Sopenharmony_ci#include "clinic/_lsprof.c.h" 667db96d56Sopenharmony_ci 677db96d56Sopenharmony_citypedef struct { 687db96d56Sopenharmony_ci PyTypeObject *profiler_type; 697db96d56Sopenharmony_ci PyTypeObject *stats_entry_type; 707db96d56Sopenharmony_ci PyTypeObject *stats_subentry_type; 717db96d56Sopenharmony_ci} _lsprof_state; 727db96d56Sopenharmony_ci 737db96d56Sopenharmony_cistatic inline _lsprof_state* 747db96d56Sopenharmony_ci_lsprof_get_state(PyObject *module) 757db96d56Sopenharmony_ci{ 767db96d56Sopenharmony_ci void *state = PyModule_GetState(module); 777db96d56Sopenharmony_ci assert(state != NULL); 787db96d56Sopenharmony_ci return (_lsprof_state *)state; 797db96d56Sopenharmony_ci} 807db96d56Sopenharmony_ci 817db96d56Sopenharmony_ci/*** External Timers ***/ 827db96d56Sopenharmony_ci 837db96d56Sopenharmony_cistatic _PyTime_t CallExternalTimer(ProfilerObject *pObj) 847db96d56Sopenharmony_ci{ 857db96d56Sopenharmony_ci PyObject *o = _PyObject_CallNoArgs(pObj->externalTimer); 867db96d56Sopenharmony_ci if (o == NULL) { 877db96d56Sopenharmony_ci PyErr_WriteUnraisable(pObj->externalTimer); 887db96d56Sopenharmony_ci return 0; 897db96d56Sopenharmony_ci } 907db96d56Sopenharmony_ci 917db96d56Sopenharmony_ci _PyTime_t result; 927db96d56Sopenharmony_ci int err; 937db96d56Sopenharmony_ci if (pObj->externalTimerUnit > 0.0) { 947db96d56Sopenharmony_ci /* interpret the result as an integer that will be scaled 957db96d56Sopenharmony_ci in profiler_getstats() */ 967db96d56Sopenharmony_ci err = _PyTime_FromNanosecondsObject(&result, o); 977db96d56Sopenharmony_ci } 987db96d56Sopenharmony_ci else { 997db96d56Sopenharmony_ci /* interpret the result as a double measured in seconds. 1007db96d56Sopenharmony_ci As the profiler works with _PyTime_t internally 1017db96d56Sopenharmony_ci we convert it to a large integer */ 1027db96d56Sopenharmony_ci err = _PyTime_FromSecondsObject(&result, o, _PyTime_ROUND_FLOOR); 1037db96d56Sopenharmony_ci } 1047db96d56Sopenharmony_ci Py_DECREF(o); 1057db96d56Sopenharmony_ci if (err < 0) { 1067db96d56Sopenharmony_ci PyErr_WriteUnraisable(pObj->externalTimer); 1077db96d56Sopenharmony_ci return 0; 1087db96d56Sopenharmony_ci } 1097db96d56Sopenharmony_ci return result; 1107db96d56Sopenharmony_ci} 1117db96d56Sopenharmony_ci 1127db96d56Sopenharmony_cistatic inline _PyTime_t 1137db96d56Sopenharmony_cicall_timer(ProfilerObject *pObj) 1147db96d56Sopenharmony_ci{ 1157db96d56Sopenharmony_ci if (pObj->externalTimer != NULL) { 1167db96d56Sopenharmony_ci return CallExternalTimer(pObj); 1177db96d56Sopenharmony_ci } 1187db96d56Sopenharmony_ci else { 1197db96d56Sopenharmony_ci return _PyTime_GetPerfCounter(); 1207db96d56Sopenharmony_ci } 1217db96d56Sopenharmony_ci} 1227db96d56Sopenharmony_ci 1237db96d56Sopenharmony_ci 1247db96d56Sopenharmony_ci/*** ProfilerObject ***/ 1257db96d56Sopenharmony_ci 1267db96d56Sopenharmony_cistatic PyObject * 1277db96d56Sopenharmony_cinormalizeUserObj(PyObject *obj) 1287db96d56Sopenharmony_ci{ 1297db96d56Sopenharmony_ci PyCFunctionObject *fn; 1307db96d56Sopenharmony_ci if (!PyCFunction_Check(obj)) { 1317db96d56Sopenharmony_ci Py_INCREF(obj); 1327db96d56Sopenharmony_ci return obj; 1337db96d56Sopenharmony_ci } 1347db96d56Sopenharmony_ci /* Replace built-in function objects with a descriptive string 1357db96d56Sopenharmony_ci because of built-in methods -- keeping a reference to 1367db96d56Sopenharmony_ci __self__ is probably not a good idea. */ 1377db96d56Sopenharmony_ci fn = (PyCFunctionObject *)obj; 1387db96d56Sopenharmony_ci 1397db96d56Sopenharmony_ci if (fn->m_self == NULL) { 1407db96d56Sopenharmony_ci /* built-in function: look up the module name */ 1417db96d56Sopenharmony_ci PyObject *mod = fn->m_module; 1427db96d56Sopenharmony_ci PyObject *modname = NULL; 1437db96d56Sopenharmony_ci if (mod != NULL) { 1447db96d56Sopenharmony_ci if (PyUnicode_Check(mod)) { 1457db96d56Sopenharmony_ci modname = mod; 1467db96d56Sopenharmony_ci Py_INCREF(modname); 1477db96d56Sopenharmony_ci } 1487db96d56Sopenharmony_ci else if (PyModule_Check(mod)) { 1497db96d56Sopenharmony_ci modname = PyModule_GetNameObject(mod); 1507db96d56Sopenharmony_ci if (modname == NULL) 1517db96d56Sopenharmony_ci PyErr_Clear(); 1527db96d56Sopenharmony_ci } 1537db96d56Sopenharmony_ci } 1547db96d56Sopenharmony_ci if (modname != NULL) { 1557db96d56Sopenharmony_ci if (!_PyUnicode_EqualToASCIIString(modname, "builtins")) { 1567db96d56Sopenharmony_ci PyObject *result; 1577db96d56Sopenharmony_ci result = PyUnicode_FromFormat("<%U.%s>", modname, 1587db96d56Sopenharmony_ci fn->m_ml->ml_name); 1597db96d56Sopenharmony_ci Py_DECREF(modname); 1607db96d56Sopenharmony_ci return result; 1617db96d56Sopenharmony_ci } 1627db96d56Sopenharmony_ci Py_DECREF(modname); 1637db96d56Sopenharmony_ci } 1647db96d56Sopenharmony_ci return PyUnicode_FromFormat("<%s>", fn->m_ml->ml_name); 1657db96d56Sopenharmony_ci } 1667db96d56Sopenharmony_ci else { 1677db96d56Sopenharmony_ci /* built-in method: try to return 1687db96d56Sopenharmony_ci repr(getattr(type(__self__), __name__)) 1697db96d56Sopenharmony_ci */ 1707db96d56Sopenharmony_ci PyObject *self = fn->m_self; 1717db96d56Sopenharmony_ci PyObject *name = PyUnicode_FromString(fn->m_ml->ml_name); 1727db96d56Sopenharmony_ci PyObject *modname = fn->m_module; 1737db96d56Sopenharmony_ci 1747db96d56Sopenharmony_ci if (name != NULL) { 1757db96d56Sopenharmony_ci PyObject *mo = _PyType_Lookup(Py_TYPE(self), name); 1767db96d56Sopenharmony_ci Py_XINCREF(mo); 1777db96d56Sopenharmony_ci Py_DECREF(name); 1787db96d56Sopenharmony_ci if (mo != NULL) { 1797db96d56Sopenharmony_ci PyObject *res = PyObject_Repr(mo); 1807db96d56Sopenharmony_ci Py_DECREF(mo); 1817db96d56Sopenharmony_ci if (res != NULL) 1827db96d56Sopenharmony_ci return res; 1837db96d56Sopenharmony_ci } 1847db96d56Sopenharmony_ci } 1857db96d56Sopenharmony_ci /* Otherwise, use __module__ */ 1867db96d56Sopenharmony_ci PyErr_Clear(); 1877db96d56Sopenharmony_ci if (modname != NULL && PyUnicode_Check(modname)) 1887db96d56Sopenharmony_ci return PyUnicode_FromFormat("<built-in method %S.%s>", 1897db96d56Sopenharmony_ci modname, fn->m_ml->ml_name); 1907db96d56Sopenharmony_ci else 1917db96d56Sopenharmony_ci return PyUnicode_FromFormat("<built-in method %s>", 1927db96d56Sopenharmony_ci fn->m_ml->ml_name); 1937db96d56Sopenharmony_ci } 1947db96d56Sopenharmony_ci} 1957db96d56Sopenharmony_ci 1967db96d56Sopenharmony_cistatic ProfilerEntry* 1977db96d56Sopenharmony_cinewProfilerEntry(ProfilerObject *pObj, void *key, PyObject *userObj) 1987db96d56Sopenharmony_ci{ 1997db96d56Sopenharmony_ci ProfilerEntry *self; 2007db96d56Sopenharmony_ci self = (ProfilerEntry*) PyMem_Malloc(sizeof(ProfilerEntry)); 2017db96d56Sopenharmony_ci if (self == NULL) { 2027db96d56Sopenharmony_ci pObj->flags |= POF_NOMEMORY; 2037db96d56Sopenharmony_ci return NULL; 2047db96d56Sopenharmony_ci } 2057db96d56Sopenharmony_ci userObj = normalizeUserObj(userObj); 2067db96d56Sopenharmony_ci if (userObj == NULL) { 2077db96d56Sopenharmony_ci PyErr_Clear(); 2087db96d56Sopenharmony_ci PyMem_Free(self); 2097db96d56Sopenharmony_ci pObj->flags |= POF_NOMEMORY; 2107db96d56Sopenharmony_ci return NULL; 2117db96d56Sopenharmony_ci } 2127db96d56Sopenharmony_ci self->header.key = key; 2137db96d56Sopenharmony_ci self->userObj = userObj; 2147db96d56Sopenharmony_ci self->tt = 0; 2157db96d56Sopenharmony_ci self->it = 0; 2167db96d56Sopenharmony_ci self->callcount = 0; 2177db96d56Sopenharmony_ci self->recursivecallcount = 0; 2187db96d56Sopenharmony_ci self->recursionLevel = 0; 2197db96d56Sopenharmony_ci self->calls = EMPTY_ROTATING_TREE; 2207db96d56Sopenharmony_ci RotatingTree_Add(&pObj->profilerEntries, &self->header); 2217db96d56Sopenharmony_ci return self; 2227db96d56Sopenharmony_ci} 2237db96d56Sopenharmony_ci 2247db96d56Sopenharmony_cistatic ProfilerEntry* 2257db96d56Sopenharmony_cigetEntry(ProfilerObject *pObj, void *key) 2267db96d56Sopenharmony_ci{ 2277db96d56Sopenharmony_ci return (ProfilerEntry*) RotatingTree_Get(&pObj->profilerEntries, key); 2287db96d56Sopenharmony_ci} 2297db96d56Sopenharmony_ci 2307db96d56Sopenharmony_cistatic ProfilerSubEntry * 2317db96d56Sopenharmony_cigetSubEntry(ProfilerObject *pObj, ProfilerEntry *caller, ProfilerEntry* entry) 2327db96d56Sopenharmony_ci{ 2337db96d56Sopenharmony_ci return (ProfilerSubEntry*) RotatingTree_Get(&caller->calls, 2347db96d56Sopenharmony_ci (void *)entry); 2357db96d56Sopenharmony_ci} 2367db96d56Sopenharmony_ci 2377db96d56Sopenharmony_cistatic ProfilerSubEntry * 2387db96d56Sopenharmony_cinewSubEntry(ProfilerObject *pObj, ProfilerEntry *caller, ProfilerEntry* entry) 2397db96d56Sopenharmony_ci{ 2407db96d56Sopenharmony_ci ProfilerSubEntry *self; 2417db96d56Sopenharmony_ci self = (ProfilerSubEntry*) PyMem_Malloc(sizeof(ProfilerSubEntry)); 2427db96d56Sopenharmony_ci if (self == NULL) { 2437db96d56Sopenharmony_ci pObj->flags |= POF_NOMEMORY; 2447db96d56Sopenharmony_ci return NULL; 2457db96d56Sopenharmony_ci } 2467db96d56Sopenharmony_ci self->header.key = (void *)entry; 2477db96d56Sopenharmony_ci self->tt = 0; 2487db96d56Sopenharmony_ci self->it = 0; 2497db96d56Sopenharmony_ci self->callcount = 0; 2507db96d56Sopenharmony_ci self->recursivecallcount = 0; 2517db96d56Sopenharmony_ci self->recursionLevel = 0; 2527db96d56Sopenharmony_ci RotatingTree_Add(&caller->calls, &self->header); 2537db96d56Sopenharmony_ci return self; 2547db96d56Sopenharmony_ci} 2557db96d56Sopenharmony_ci 2567db96d56Sopenharmony_cistatic int freeSubEntry(rotating_node_t *header, void *arg) 2577db96d56Sopenharmony_ci{ 2587db96d56Sopenharmony_ci ProfilerSubEntry *subentry = (ProfilerSubEntry*) header; 2597db96d56Sopenharmony_ci PyMem_Free(subentry); 2607db96d56Sopenharmony_ci return 0; 2617db96d56Sopenharmony_ci} 2627db96d56Sopenharmony_ci 2637db96d56Sopenharmony_cistatic int freeEntry(rotating_node_t *header, void *arg) 2647db96d56Sopenharmony_ci{ 2657db96d56Sopenharmony_ci ProfilerEntry *entry = (ProfilerEntry*) header; 2667db96d56Sopenharmony_ci RotatingTree_Enum(entry->calls, freeSubEntry, NULL); 2677db96d56Sopenharmony_ci Py_DECREF(entry->userObj); 2687db96d56Sopenharmony_ci PyMem_Free(entry); 2697db96d56Sopenharmony_ci return 0; 2707db96d56Sopenharmony_ci} 2717db96d56Sopenharmony_ci 2727db96d56Sopenharmony_cistatic void clearEntries(ProfilerObject *pObj) 2737db96d56Sopenharmony_ci{ 2747db96d56Sopenharmony_ci RotatingTree_Enum(pObj->profilerEntries, freeEntry, NULL); 2757db96d56Sopenharmony_ci pObj->profilerEntries = EMPTY_ROTATING_TREE; 2767db96d56Sopenharmony_ci /* release the memory hold by the ProfilerContexts */ 2777db96d56Sopenharmony_ci if (pObj->currentProfilerContext) { 2787db96d56Sopenharmony_ci PyMem_Free(pObj->currentProfilerContext); 2797db96d56Sopenharmony_ci pObj->currentProfilerContext = NULL; 2807db96d56Sopenharmony_ci } 2817db96d56Sopenharmony_ci while (pObj->freelistProfilerContext) { 2827db96d56Sopenharmony_ci ProfilerContext *c = pObj->freelistProfilerContext; 2837db96d56Sopenharmony_ci pObj->freelistProfilerContext = c->previous; 2847db96d56Sopenharmony_ci PyMem_Free(c); 2857db96d56Sopenharmony_ci } 2867db96d56Sopenharmony_ci pObj->freelistProfilerContext = NULL; 2877db96d56Sopenharmony_ci} 2887db96d56Sopenharmony_ci 2897db96d56Sopenharmony_cistatic void 2907db96d56Sopenharmony_ciinitContext(ProfilerObject *pObj, ProfilerContext *self, ProfilerEntry *entry) 2917db96d56Sopenharmony_ci{ 2927db96d56Sopenharmony_ci self->ctxEntry = entry; 2937db96d56Sopenharmony_ci self->subt = 0; 2947db96d56Sopenharmony_ci self->previous = pObj->currentProfilerContext; 2957db96d56Sopenharmony_ci pObj->currentProfilerContext = self; 2967db96d56Sopenharmony_ci ++entry->recursionLevel; 2977db96d56Sopenharmony_ci if ((pObj->flags & POF_SUBCALLS) && self->previous) { 2987db96d56Sopenharmony_ci /* find or create an entry for me in my caller's entry */ 2997db96d56Sopenharmony_ci ProfilerEntry *caller = self->previous->ctxEntry; 3007db96d56Sopenharmony_ci ProfilerSubEntry *subentry = getSubEntry(pObj, caller, entry); 3017db96d56Sopenharmony_ci if (subentry == NULL) 3027db96d56Sopenharmony_ci subentry = newSubEntry(pObj, caller, entry); 3037db96d56Sopenharmony_ci if (subentry) 3047db96d56Sopenharmony_ci ++subentry->recursionLevel; 3057db96d56Sopenharmony_ci } 3067db96d56Sopenharmony_ci self->t0 = call_timer(pObj); 3077db96d56Sopenharmony_ci} 3087db96d56Sopenharmony_ci 3097db96d56Sopenharmony_cistatic void 3107db96d56Sopenharmony_ciStop(ProfilerObject *pObj, ProfilerContext *self, ProfilerEntry *entry) 3117db96d56Sopenharmony_ci{ 3127db96d56Sopenharmony_ci _PyTime_t tt = call_timer(pObj) - self->t0; 3137db96d56Sopenharmony_ci _PyTime_t it = tt - self->subt; 3147db96d56Sopenharmony_ci if (self->previous) 3157db96d56Sopenharmony_ci self->previous->subt += tt; 3167db96d56Sopenharmony_ci pObj->currentProfilerContext = self->previous; 3177db96d56Sopenharmony_ci if (--entry->recursionLevel == 0) 3187db96d56Sopenharmony_ci entry->tt += tt; 3197db96d56Sopenharmony_ci else 3207db96d56Sopenharmony_ci ++entry->recursivecallcount; 3217db96d56Sopenharmony_ci entry->it += it; 3227db96d56Sopenharmony_ci entry->callcount++; 3237db96d56Sopenharmony_ci if ((pObj->flags & POF_SUBCALLS) && self->previous) { 3247db96d56Sopenharmony_ci /* find or create an entry for me in my caller's entry */ 3257db96d56Sopenharmony_ci ProfilerEntry *caller = self->previous->ctxEntry; 3267db96d56Sopenharmony_ci ProfilerSubEntry *subentry = getSubEntry(pObj, caller, entry); 3277db96d56Sopenharmony_ci if (subentry) { 3287db96d56Sopenharmony_ci if (--subentry->recursionLevel == 0) 3297db96d56Sopenharmony_ci subentry->tt += tt; 3307db96d56Sopenharmony_ci else 3317db96d56Sopenharmony_ci ++subentry->recursivecallcount; 3327db96d56Sopenharmony_ci subentry->it += it; 3337db96d56Sopenharmony_ci ++subentry->callcount; 3347db96d56Sopenharmony_ci } 3357db96d56Sopenharmony_ci } 3367db96d56Sopenharmony_ci} 3377db96d56Sopenharmony_ci 3387db96d56Sopenharmony_cistatic void 3397db96d56Sopenharmony_ciptrace_enter_call(PyObject *self, void *key, PyObject *userObj) 3407db96d56Sopenharmony_ci{ 3417db96d56Sopenharmony_ci /* entering a call to the function identified by 'key' 3427db96d56Sopenharmony_ci (which can be a PyCodeObject or a PyMethodDef pointer) */ 3437db96d56Sopenharmony_ci ProfilerObject *pObj = (ProfilerObject*)self; 3447db96d56Sopenharmony_ci ProfilerEntry *profEntry; 3457db96d56Sopenharmony_ci ProfilerContext *pContext; 3467db96d56Sopenharmony_ci 3477db96d56Sopenharmony_ci /* In the case of entering a generator expression frame via a 3487db96d56Sopenharmony_ci * throw (gen_send_ex(.., 1)), we may already have an 3497db96d56Sopenharmony_ci * Exception set here. We must not mess around with this 3507db96d56Sopenharmony_ci * exception, and some of the code under here assumes that 3517db96d56Sopenharmony_ci * PyErr_* is its own to mess around with, so we have to 3527db96d56Sopenharmony_ci * save and restore any current exception. */ 3537db96d56Sopenharmony_ci PyObject *last_type, *last_value, *last_tb; 3547db96d56Sopenharmony_ci PyErr_Fetch(&last_type, &last_value, &last_tb); 3557db96d56Sopenharmony_ci 3567db96d56Sopenharmony_ci profEntry = getEntry(pObj, key); 3577db96d56Sopenharmony_ci if (profEntry == NULL) { 3587db96d56Sopenharmony_ci profEntry = newProfilerEntry(pObj, key, userObj); 3597db96d56Sopenharmony_ci if (profEntry == NULL) 3607db96d56Sopenharmony_ci goto restorePyerr; 3617db96d56Sopenharmony_ci } 3627db96d56Sopenharmony_ci /* grab a ProfilerContext out of the free list */ 3637db96d56Sopenharmony_ci pContext = pObj->freelistProfilerContext; 3647db96d56Sopenharmony_ci if (pContext) { 3657db96d56Sopenharmony_ci pObj->freelistProfilerContext = pContext->previous; 3667db96d56Sopenharmony_ci } 3677db96d56Sopenharmony_ci else { 3687db96d56Sopenharmony_ci /* free list exhausted, allocate a new one */ 3697db96d56Sopenharmony_ci pContext = (ProfilerContext*) 3707db96d56Sopenharmony_ci PyMem_Malloc(sizeof(ProfilerContext)); 3717db96d56Sopenharmony_ci if (pContext == NULL) { 3727db96d56Sopenharmony_ci pObj->flags |= POF_NOMEMORY; 3737db96d56Sopenharmony_ci goto restorePyerr; 3747db96d56Sopenharmony_ci } 3757db96d56Sopenharmony_ci } 3767db96d56Sopenharmony_ci initContext(pObj, pContext, profEntry); 3777db96d56Sopenharmony_ci 3787db96d56Sopenharmony_cirestorePyerr: 3797db96d56Sopenharmony_ci PyErr_Restore(last_type, last_value, last_tb); 3807db96d56Sopenharmony_ci} 3817db96d56Sopenharmony_ci 3827db96d56Sopenharmony_cistatic void 3837db96d56Sopenharmony_ciptrace_leave_call(PyObject *self, void *key) 3847db96d56Sopenharmony_ci{ 3857db96d56Sopenharmony_ci /* leaving a call to the function identified by 'key' */ 3867db96d56Sopenharmony_ci ProfilerObject *pObj = (ProfilerObject*)self; 3877db96d56Sopenharmony_ci ProfilerEntry *profEntry; 3887db96d56Sopenharmony_ci ProfilerContext *pContext; 3897db96d56Sopenharmony_ci 3907db96d56Sopenharmony_ci pContext = pObj->currentProfilerContext; 3917db96d56Sopenharmony_ci if (pContext == NULL) 3927db96d56Sopenharmony_ci return; 3937db96d56Sopenharmony_ci profEntry = getEntry(pObj, key); 3947db96d56Sopenharmony_ci if (profEntry) { 3957db96d56Sopenharmony_ci Stop(pObj, pContext, profEntry); 3967db96d56Sopenharmony_ci } 3977db96d56Sopenharmony_ci else { 3987db96d56Sopenharmony_ci pObj->currentProfilerContext = pContext->previous; 3997db96d56Sopenharmony_ci } 4007db96d56Sopenharmony_ci /* put pContext into the free list */ 4017db96d56Sopenharmony_ci pContext->previous = pObj->freelistProfilerContext; 4027db96d56Sopenharmony_ci pObj->freelistProfilerContext = pContext; 4037db96d56Sopenharmony_ci} 4047db96d56Sopenharmony_ci 4057db96d56Sopenharmony_cistatic int 4067db96d56Sopenharmony_ciprofiler_callback(PyObject *self, PyFrameObject *frame, int what, 4077db96d56Sopenharmony_ci PyObject *arg) 4087db96d56Sopenharmony_ci{ 4097db96d56Sopenharmony_ci switch (what) { 4107db96d56Sopenharmony_ci 4117db96d56Sopenharmony_ci /* the 'frame' of a called function is about to start its execution */ 4127db96d56Sopenharmony_ci case PyTrace_CALL: 4137db96d56Sopenharmony_ci { 4147db96d56Sopenharmony_ci PyCodeObject *code = PyFrame_GetCode(frame); 4157db96d56Sopenharmony_ci ptrace_enter_call(self, (void *)code, (PyObject *)code); 4167db96d56Sopenharmony_ci Py_DECREF(code); 4177db96d56Sopenharmony_ci break; 4187db96d56Sopenharmony_ci } 4197db96d56Sopenharmony_ci 4207db96d56Sopenharmony_ci /* the 'frame' of a called function is about to finish 4217db96d56Sopenharmony_ci (either normally or with an exception) */ 4227db96d56Sopenharmony_ci case PyTrace_RETURN: 4237db96d56Sopenharmony_ci { 4247db96d56Sopenharmony_ci PyCodeObject *code = PyFrame_GetCode(frame); 4257db96d56Sopenharmony_ci ptrace_leave_call(self, (void *)code); 4267db96d56Sopenharmony_ci Py_DECREF(code); 4277db96d56Sopenharmony_ci break; 4287db96d56Sopenharmony_ci } 4297db96d56Sopenharmony_ci 4307db96d56Sopenharmony_ci /* case PyTrace_EXCEPTION: 4317db96d56Sopenharmony_ci If the exception results in the function exiting, a 4327db96d56Sopenharmony_ci PyTrace_RETURN event will be generated, so we don't need to 4337db96d56Sopenharmony_ci handle it. */ 4347db96d56Sopenharmony_ci 4357db96d56Sopenharmony_ci /* the Python function 'frame' is issuing a call to the built-in 4367db96d56Sopenharmony_ci function 'arg' */ 4377db96d56Sopenharmony_ci case PyTrace_C_CALL: 4387db96d56Sopenharmony_ci if ((((ProfilerObject *)self)->flags & POF_BUILTINS) 4397db96d56Sopenharmony_ci && PyCFunction_Check(arg)) { 4407db96d56Sopenharmony_ci ptrace_enter_call(self, 4417db96d56Sopenharmony_ci ((PyCFunctionObject *)arg)->m_ml, 4427db96d56Sopenharmony_ci arg); 4437db96d56Sopenharmony_ci } 4447db96d56Sopenharmony_ci break; 4457db96d56Sopenharmony_ci 4467db96d56Sopenharmony_ci /* the call to the built-in function 'arg' is returning into its 4477db96d56Sopenharmony_ci caller 'frame' */ 4487db96d56Sopenharmony_ci case PyTrace_C_RETURN: /* ...normally */ 4497db96d56Sopenharmony_ci case PyTrace_C_EXCEPTION: /* ...with an exception set */ 4507db96d56Sopenharmony_ci if ((((ProfilerObject *)self)->flags & POF_BUILTINS) 4517db96d56Sopenharmony_ci && PyCFunction_Check(arg)) { 4527db96d56Sopenharmony_ci ptrace_leave_call(self, 4537db96d56Sopenharmony_ci ((PyCFunctionObject *)arg)->m_ml); 4547db96d56Sopenharmony_ci } 4557db96d56Sopenharmony_ci break; 4567db96d56Sopenharmony_ci 4577db96d56Sopenharmony_ci default: 4587db96d56Sopenharmony_ci break; 4597db96d56Sopenharmony_ci } 4607db96d56Sopenharmony_ci return 0; 4617db96d56Sopenharmony_ci} 4627db96d56Sopenharmony_ci 4637db96d56Sopenharmony_cistatic int 4647db96d56Sopenharmony_cipending_exception(ProfilerObject *pObj) 4657db96d56Sopenharmony_ci{ 4667db96d56Sopenharmony_ci if (pObj->flags & POF_NOMEMORY) { 4677db96d56Sopenharmony_ci pObj->flags -= POF_NOMEMORY; 4687db96d56Sopenharmony_ci PyErr_SetString(PyExc_MemoryError, 4697db96d56Sopenharmony_ci "memory was exhausted while profiling"); 4707db96d56Sopenharmony_ci return -1; 4717db96d56Sopenharmony_ci } 4727db96d56Sopenharmony_ci return 0; 4737db96d56Sopenharmony_ci} 4747db96d56Sopenharmony_ci 4757db96d56Sopenharmony_ci/************************************************************/ 4767db96d56Sopenharmony_ci 4777db96d56Sopenharmony_cistatic PyStructSequence_Field profiler_entry_fields[] = { 4787db96d56Sopenharmony_ci {"code", "code object or built-in function name"}, 4797db96d56Sopenharmony_ci {"callcount", "how many times this was called"}, 4807db96d56Sopenharmony_ci {"reccallcount", "how many times called recursively"}, 4817db96d56Sopenharmony_ci {"totaltime", "total time in this entry"}, 4827db96d56Sopenharmony_ci {"inlinetime", "inline time in this entry (not in subcalls)"}, 4837db96d56Sopenharmony_ci {"calls", "details of the calls"}, 4847db96d56Sopenharmony_ci {0} 4857db96d56Sopenharmony_ci}; 4867db96d56Sopenharmony_ci 4877db96d56Sopenharmony_cistatic PyStructSequence_Field profiler_subentry_fields[] = { 4887db96d56Sopenharmony_ci {"code", "called code object or built-in function name"}, 4897db96d56Sopenharmony_ci {"callcount", "how many times this is called"}, 4907db96d56Sopenharmony_ci {"reccallcount", "how many times this is called recursively"}, 4917db96d56Sopenharmony_ci {"totaltime", "total time spent in this call"}, 4927db96d56Sopenharmony_ci {"inlinetime", "inline time (not in further subcalls)"}, 4937db96d56Sopenharmony_ci {0} 4947db96d56Sopenharmony_ci}; 4957db96d56Sopenharmony_ci 4967db96d56Sopenharmony_cistatic PyStructSequence_Desc profiler_entry_desc = { 4977db96d56Sopenharmony_ci .name = "_lsprof.profiler_entry", 4987db96d56Sopenharmony_ci .fields = profiler_entry_fields, 4997db96d56Sopenharmony_ci .doc = NULL, 5007db96d56Sopenharmony_ci .n_in_sequence = 6 5017db96d56Sopenharmony_ci}; 5027db96d56Sopenharmony_ci 5037db96d56Sopenharmony_cistatic PyStructSequence_Desc profiler_subentry_desc = { 5047db96d56Sopenharmony_ci .name = "_lsprof.profiler_subentry", 5057db96d56Sopenharmony_ci .fields = profiler_subentry_fields, 5067db96d56Sopenharmony_ci .doc = NULL, 5077db96d56Sopenharmony_ci .n_in_sequence = 5 5087db96d56Sopenharmony_ci}; 5097db96d56Sopenharmony_ci 5107db96d56Sopenharmony_citypedef struct { 5117db96d56Sopenharmony_ci PyObject *list; 5127db96d56Sopenharmony_ci PyObject *sublist; 5137db96d56Sopenharmony_ci double factor; 5147db96d56Sopenharmony_ci _lsprof_state *state; 5157db96d56Sopenharmony_ci} statscollector_t; 5167db96d56Sopenharmony_ci 5177db96d56Sopenharmony_cistatic int statsForSubEntry(rotating_node_t *node, void *arg) 5187db96d56Sopenharmony_ci{ 5197db96d56Sopenharmony_ci ProfilerSubEntry *sentry = (ProfilerSubEntry*) node; 5207db96d56Sopenharmony_ci statscollector_t *collect = (statscollector_t*) arg; 5217db96d56Sopenharmony_ci ProfilerEntry *entry = (ProfilerEntry*) sentry->header.key; 5227db96d56Sopenharmony_ci int err; 5237db96d56Sopenharmony_ci PyObject *sinfo; 5247db96d56Sopenharmony_ci sinfo = PyObject_CallFunction((PyObject*) collect->state->stats_subentry_type, 5257db96d56Sopenharmony_ci "((Olldd))", 5267db96d56Sopenharmony_ci entry->userObj, 5277db96d56Sopenharmony_ci sentry->callcount, 5287db96d56Sopenharmony_ci sentry->recursivecallcount, 5297db96d56Sopenharmony_ci collect->factor * sentry->tt, 5307db96d56Sopenharmony_ci collect->factor * sentry->it); 5317db96d56Sopenharmony_ci if (sinfo == NULL) 5327db96d56Sopenharmony_ci return -1; 5337db96d56Sopenharmony_ci err = PyList_Append(collect->sublist, sinfo); 5347db96d56Sopenharmony_ci Py_DECREF(sinfo); 5357db96d56Sopenharmony_ci return err; 5367db96d56Sopenharmony_ci} 5377db96d56Sopenharmony_ci 5387db96d56Sopenharmony_cistatic int statsForEntry(rotating_node_t *node, void *arg) 5397db96d56Sopenharmony_ci{ 5407db96d56Sopenharmony_ci ProfilerEntry *entry = (ProfilerEntry*) node; 5417db96d56Sopenharmony_ci statscollector_t *collect = (statscollector_t*) arg; 5427db96d56Sopenharmony_ci PyObject *info; 5437db96d56Sopenharmony_ci int err; 5447db96d56Sopenharmony_ci if (entry->callcount == 0) 5457db96d56Sopenharmony_ci return 0; /* skip */ 5467db96d56Sopenharmony_ci 5477db96d56Sopenharmony_ci if (entry->calls != EMPTY_ROTATING_TREE) { 5487db96d56Sopenharmony_ci collect->sublist = PyList_New(0); 5497db96d56Sopenharmony_ci if (collect->sublist == NULL) 5507db96d56Sopenharmony_ci return -1; 5517db96d56Sopenharmony_ci if (RotatingTree_Enum(entry->calls, 5527db96d56Sopenharmony_ci statsForSubEntry, collect) != 0) { 5537db96d56Sopenharmony_ci Py_DECREF(collect->sublist); 5547db96d56Sopenharmony_ci return -1; 5557db96d56Sopenharmony_ci } 5567db96d56Sopenharmony_ci } 5577db96d56Sopenharmony_ci else { 5587db96d56Sopenharmony_ci Py_INCREF(Py_None); 5597db96d56Sopenharmony_ci collect->sublist = Py_None; 5607db96d56Sopenharmony_ci } 5617db96d56Sopenharmony_ci 5627db96d56Sopenharmony_ci info = PyObject_CallFunction((PyObject*) collect->state->stats_entry_type, 5637db96d56Sopenharmony_ci "((OllddO))", 5647db96d56Sopenharmony_ci entry->userObj, 5657db96d56Sopenharmony_ci entry->callcount, 5667db96d56Sopenharmony_ci entry->recursivecallcount, 5677db96d56Sopenharmony_ci collect->factor * entry->tt, 5687db96d56Sopenharmony_ci collect->factor * entry->it, 5697db96d56Sopenharmony_ci collect->sublist); 5707db96d56Sopenharmony_ci Py_DECREF(collect->sublist); 5717db96d56Sopenharmony_ci if (info == NULL) 5727db96d56Sopenharmony_ci return -1; 5737db96d56Sopenharmony_ci err = PyList_Append(collect->list, info); 5747db96d56Sopenharmony_ci Py_DECREF(info); 5757db96d56Sopenharmony_ci return err; 5767db96d56Sopenharmony_ci} 5777db96d56Sopenharmony_ci 5787db96d56Sopenharmony_ci/*[clinic input] 5797db96d56Sopenharmony_ci_lsprof.Profiler.getstats 5807db96d56Sopenharmony_ci 5817db96d56Sopenharmony_ci cls: defining_class 5827db96d56Sopenharmony_ci 5837db96d56Sopenharmony_cilist of profiler_entry objects. 5847db96d56Sopenharmony_ci 5857db96d56Sopenharmony_cigetstats() -> list of profiler_entry objects 5867db96d56Sopenharmony_ci 5877db96d56Sopenharmony_ciReturn all information collected by the profiler. 5887db96d56Sopenharmony_ciEach profiler_entry is a tuple-like object with the 5897db96d56Sopenharmony_cifollowing attributes: 5907db96d56Sopenharmony_ci 5917db96d56Sopenharmony_ci code code object 5927db96d56Sopenharmony_ci callcount how many times this was called 5937db96d56Sopenharmony_ci reccallcount how many times called recursively 5947db96d56Sopenharmony_ci totaltime total time in this entry 5957db96d56Sopenharmony_ci inlinetime inline time in this entry (not in subcalls) 5967db96d56Sopenharmony_ci calls details of the calls 5977db96d56Sopenharmony_ci 5987db96d56Sopenharmony_ciThe calls attribute is either None or a list of 5997db96d56Sopenharmony_ciprofiler_subentry objects: 6007db96d56Sopenharmony_ci 6017db96d56Sopenharmony_ci code called code object 6027db96d56Sopenharmony_ci callcount how many times this is called 6037db96d56Sopenharmony_ci reccallcount how many times this is called recursively 6047db96d56Sopenharmony_ci totaltime total time spent in this call 6057db96d56Sopenharmony_ci inlinetime inline time (not in further subcalls) 6067db96d56Sopenharmony_ci[clinic start generated code]*/ 6077db96d56Sopenharmony_ci 6087db96d56Sopenharmony_cistatic PyObject * 6097db96d56Sopenharmony_ci_lsprof_Profiler_getstats_impl(ProfilerObject *self, PyTypeObject *cls) 6107db96d56Sopenharmony_ci/*[clinic end generated code: output=1806ef720019ee03 input=445e193ef4522902]*/ 6117db96d56Sopenharmony_ci{ 6127db96d56Sopenharmony_ci statscollector_t collect; 6137db96d56Sopenharmony_ci collect.state = PyType_GetModuleState(cls); 6147db96d56Sopenharmony_ci if (pending_exception(self)) { 6157db96d56Sopenharmony_ci return NULL; 6167db96d56Sopenharmony_ci } 6177db96d56Sopenharmony_ci if (!self->externalTimer || self->externalTimerUnit == 0.0) { 6187db96d56Sopenharmony_ci _PyTime_t onesec = _PyTime_FromSeconds(1); 6197db96d56Sopenharmony_ci collect.factor = (double)1 / onesec; 6207db96d56Sopenharmony_ci } 6217db96d56Sopenharmony_ci else { 6227db96d56Sopenharmony_ci collect.factor = self->externalTimerUnit; 6237db96d56Sopenharmony_ci } 6247db96d56Sopenharmony_ci 6257db96d56Sopenharmony_ci collect.list = PyList_New(0); 6267db96d56Sopenharmony_ci if (collect.list == NULL) 6277db96d56Sopenharmony_ci return NULL; 6287db96d56Sopenharmony_ci if (RotatingTree_Enum(self->profilerEntries, statsForEntry, &collect) 6297db96d56Sopenharmony_ci != 0) { 6307db96d56Sopenharmony_ci Py_DECREF(collect.list); 6317db96d56Sopenharmony_ci return NULL; 6327db96d56Sopenharmony_ci } 6337db96d56Sopenharmony_ci return collect.list; 6347db96d56Sopenharmony_ci} 6357db96d56Sopenharmony_ci 6367db96d56Sopenharmony_cistatic int 6377db96d56Sopenharmony_cisetSubcalls(ProfilerObject *pObj, int nvalue) 6387db96d56Sopenharmony_ci{ 6397db96d56Sopenharmony_ci if (nvalue == 0) 6407db96d56Sopenharmony_ci pObj->flags &= ~POF_SUBCALLS; 6417db96d56Sopenharmony_ci else if (nvalue > 0) 6427db96d56Sopenharmony_ci pObj->flags |= POF_SUBCALLS; 6437db96d56Sopenharmony_ci return 0; 6447db96d56Sopenharmony_ci} 6457db96d56Sopenharmony_ci 6467db96d56Sopenharmony_cistatic int 6477db96d56Sopenharmony_cisetBuiltins(ProfilerObject *pObj, int nvalue) 6487db96d56Sopenharmony_ci{ 6497db96d56Sopenharmony_ci if (nvalue == 0) 6507db96d56Sopenharmony_ci pObj->flags &= ~POF_BUILTINS; 6517db96d56Sopenharmony_ci else if (nvalue > 0) { 6527db96d56Sopenharmony_ci pObj->flags |= POF_BUILTINS; 6537db96d56Sopenharmony_ci } 6547db96d56Sopenharmony_ci return 0; 6557db96d56Sopenharmony_ci} 6567db96d56Sopenharmony_ci 6577db96d56Sopenharmony_ciPyDoc_STRVAR(enable_doc, "\ 6587db96d56Sopenharmony_cienable(subcalls=True, builtins=True)\n\ 6597db96d56Sopenharmony_ci\n\ 6607db96d56Sopenharmony_ciStart collecting profiling information.\n\ 6617db96d56Sopenharmony_ciIf 'subcalls' is True, also records for each function\n\ 6627db96d56Sopenharmony_cistatistics separated according to its current caller.\n\ 6637db96d56Sopenharmony_ciIf 'builtins' is True, records the time spent in\n\ 6647db96d56Sopenharmony_cibuilt-in functions separately from their caller.\n\ 6657db96d56Sopenharmony_ci"); 6667db96d56Sopenharmony_ci 6677db96d56Sopenharmony_cistatic PyObject* 6687db96d56Sopenharmony_ciprofiler_enable(ProfilerObject *self, PyObject *args, PyObject *kwds) 6697db96d56Sopenharmony_ci{ 6707db96d56Sopenharmony_ci int subcalls = -1; 6717db96d56Sopenharmony_ci int builtins = -1; 6727db96d56Sopenharmony_ci static char *kwlist[] = {"subcalls", "builtins", 0}; 6737db96d56Sopenharmony_ci if (!PyArg_ParseTupleAndKeywords(args, kwds, "|ii:enable", 6747db96d56Sopenharmony_ci kwlist, &subcalls, &builtins)) 6757db96d56Sopenharmony_ci return NULL; 6767db96d56Sopenharmony_ci if (setSubcalls(self, subcalls) < 0 || setBuiltins(self, builtins) < 0) { 6777db96d56Sopenharmony_ci return NULL; 6787db96d56Sopenharmony_ci } 6797db96d56Sopenharmony_ci 6807db96d56Sopenharmony_ci PyThreadState *tstate = _PyThreadState_GET(); 6817db96d56Sopenharmony_ci if (_PyEval_SetProfile(tstate, profiler_callback, (PyObject*)self) < 0) { 6827db96d56Sopenharmony_ci return NULL; 6837db96d56Sopenharmony_ci } 6847db96d56Sopenharmony_ci 6857db96d56Sopenharmony_ci self->flags |= POF_ENABLED; 6867db96d56Sopenharmony_ci Py_RETURN_NONE; 6877db96d56Sopenharmony_ci} 6887db96d56Sopenharmony_ci 6897db96d56Sopenharmony_cistatic void 6907db96d56Sopenharmony_ciflush_unmatched(ProfilerObject *pObj) 6917db96d56Sopenharmony_ci{ 6927db96d56Sopenharmony_ci while (pObj->currentProfilerContext) { 6937db96d56Sopenharmony_ci ProfilerContext *pContext = pObj->currentProfilerContext; 6947db96d56Sopenharmony_ci ProfilerEntry *profEntry= pContext->ctxEntry; 6957db96d56Sopenharmony_ci if (profEntry) 6967db96d56Sopenharmony_ci Stop(pObj, pContext, profEntry); 6977db96d56Sopenharmony_ci else 6987db96d56Sopenharmony_ci pObj->currentProfilerContext = pContext->previous; 6997db96d56Sopenharmony_ci if (pContext) 7007db96d56Sopenharmony_ci PyMem_Free(pContext); 7017db96d56Sopenharmony_ci } 7027db96d56Sopenharmony_ci 7037db96d56Sopenharmony_ci} 7047db96d56Sopenharmony_ci 7057db96d56Sopenharmony_ciPyDoc_STRVAR(disable_doc, "\ 7067db96d56Sopenharmony_cidisable()\n\ 7077db96d56Sopenharmony_ci\n\ 7087db96d56Sopenharmony_ciStop collecting profiling information.\n\ 7097db96d56Sopenharmony_ci"); 7107db96d56Sopenharmony_ci 7117db96d56Sopenharmony_cistatic PyObject* 7127db96d56Sopenharmony_ciprofiler_disable(ProfilerObject *self, PyObject* noarg) 7137db96d56Sopenharmony_ci{ 7147db96d56Sopenharmony_ci PyThreadState *tstate = _PyThreadState_GET(); 7157db96d56Sopenharmony_ci if (_PyEval_SetProfile(tstate, NULL, NULL) < 0) { 7167db96d56Sopenharmony_ci return NULL; 7177db96d56Sopenharmony_ci } 7187db96d56Sopenharmony_ci self->flags &= ~POF_ENABLED; 7197db96d56Sopenharmony_ci 7207db96d56Sopenharmony_ci flush_unmatched(self); 7217db96d56Sopenharmony_ci if (pending_exception(self)) { 7227db96d56Sopenharmony_ci return NULL; 7237db96d56Sopenharmony_ci } 7247db96d56Sopenharmony_ci Py_RETURN_NONE; 7257db96d56Sopenharmony_ci} 7267db96d56Sopenharmony_ci 7277db96d56Sopenharmony_ciPyDoc_STRVAR(clear_doc, "\ 7287db96d56Sopenharmony_ciclear()\n\ 7297db96d56Sopenharmony_ci\n\ 7307db96d56Sopenharmony_ciClear all profiling information collected so far.\n\ 7317db96d56Sopenharmony_ci"); 7327db96d56Sopenharmony_ci 7337db96d56Sopenharmony_cistatic PyObject* 7347db96d56Sopenharmony_ciprofiler_clear(ProfilerObject *pObj, PyObject* noarg) 7357db96d56Sopenharmony_ci{ 7367db96d56Sopenharmony_ci clearEntries(pObj); 7377db96d56Sopenharmony_ci Py_RETURN_NONE; 7387db96d56Sopenharmony_ci} 7397db96d56Sopenharmony_ci 7407db96d56Sopenharmony_cistatic int 7417db96d56Sopenharmony_ciprofiler_traverse(ProfilerObject *op, visitproc visit, void *arg) 7427db96d56Sopenharmony_ci{ 7437db96d56Sopenharmony_ci Py_VISIT(Py_TYPE(op)); 7447db96d56Sopenharmony_ci return 0; 7457db96d56Sopenharmony_ci} 7467db96d56Sopenharmony_ci 7477db96d56Sopenharmony_cistatic void 7487db96d56Sopenharmony_ciprofiler_dealloc(ProfilerObject *op) 7497db96d56Sopenharmony_ci{ 7507db96d56Sopenharmony_ci PyObject_GC_UnTrack(op); 7517db96d56Sopenharmony_ci if (op->flags & POF_ENABLED) { 7527db96d56Sopenharmony_ci PyThreadState *tstate = _PyThreadState_GET(); 7537db96d56Sopenharmony_ci if (_PyEval_SetProfile(tstate, NULL, NULL) < 0) { 7547db96d56Sopenharmony_ci _PyErr_WriteUnraisableMsg("When destroying _lsprof profiler", NULL); 7557db96d56Sopenharmony_ci } 7567db96d56Sopenharmony_ci } 7577db96d56Sopenharmony_ci 7587db96d56Sopenharmony_ci flush_unmatched(op); 7597db96d56Sopenharmony_ci clearEntries(op); 7607db96d56Sopenharmony_ci Py_XDECREF(op->externalTimer); 7617db96d56Sopenharmony_ci PyTypeObject *tp = Py_TYPE(op); 7627db96d56Sopenharmony_ci tp->tp_free(op); 7637db96d56Sopenharmony_ci Py_DECREF(tp); 7647db96d56Sopenharmony_ci} 7657db96d56Sopenharmony_ci 7667db96d56Sopenharmony_cistatic int 7677db96d56Sopenharmony_ciprofiler_init(ProfilerObject *pObj, PyObject *args, PyObject *kw) 7687db96d56Sopenharmony_ci{ 7697db96d56Sopenharmony_ci PyObject *timer = NULL; 7707db96d56Sopenharmony_ci double timeunit = 0.0; 7717db96d56Sopenharmony_ci int subcalls = 1; 7727db96d56Sopenharmony_ci int builtins = 1; 7737db96d56Sopenharmony_ci static char *kwlist[] = {"timer", "timeunit", 7747db96d56Sopenharmony_ci "subcalls", "builtins", 0}; 7757db96d56Sopenharmony_ci 7767db96d56Sopenharmony_ci if (!PyArg_ParseTupleAndKeywords(args, kw, "|Odii:Profiler", kwlist, 7777db96d56Sopenharmony_ci &timer, &timeunit, 7787db96d56Sopenharmony_ci &subcalls, &builtins)) 7797db96d56Sopenharmony_ci return -1; 7807db96d56Sopenharmony_ci 7817db96d56Sopenharmony_ci if (setSubcalls(pObj, subcalls) < 0 || setBuiltins(pObj, builtins) < 0) 7827db96d56Sopenharmony_ci return -1; 7837db96d56Sopenharmony_ci pObj->externalTimerUnit = timeunit; 7847db96d56Sopenharmony_ci Py_XINCREF(timer); 7857db96d56Sopenharmony_ci Py_XSETREF(pObj->externalTimer, timer); 7867db96d56Sopenharmony_ci return 0; 7877db96d56Sopenharmony_ci} 7887db96d56Sopenharmony_ci 7897db96d56Sopenharmony_cistatic PyMethodDef profiler_methods[] = { 7907db96d56Sopenharmony_ci _LSPROF_PROFILER_GETSTATS_METHODDEF 7917db96d56Sopenharmony_ci {"enable", _PyCFunction_CAST(profiler_enable), 7927db96d56Sopenharmony_ci METH_VARARGS | METH_KEYWORDS, enable_doc}, 7937db96d56Sopenharmony_ci {"disable", (PyCFunction)profiler_disable, 7947db96d56Sopenharmony_ci METH_NOARGS, disable_doc}, 7957db96d56Sopenharmony_ci {"clear", (PyCFunction)profiler_clear, 7967db96d56Sopenharmony_ci METH_NOARGS, clear_doc}, 7977db96d56Sopenharmony_ci {NULL, NULL} 7987db96d56Sopenharmony_ci}; 7997db96d56Sopenharmony_ci 8007db96d56Sopenharmony_ciPyDoc_STRVAR(profiler_doc, "\ 8017db96d56Sopenharmony_ciProfiler(timer=None, timeunit=None, subcalls=True, builtins=True)\n\ 8027db96d56Sopenharmony_ci\n\ 8037db96d56Sopenharmony_ci Builds a profiler object using the specified timer function.\n\ 8047db96d56Sopenharmony_ci The default timer is a fast built-in one based on real time.\n\ 8057db96d56Sopenharmony_ci For custom timer functions returning integers, timeunit can\n\ 8067db96d56Sopenharmony_ci be a float specifying a scale (i.e. how long each integer unit\n\ 8077db96d56Sopenharmony_ci is, in seconds).\n\ 8087db96d56Sopenharmony_ci"); 8097db96d56Sopenharmony_ci 8107db96d56Sopenharmony_cistatic PyType_Slot _lsprof_profiler_type_spec_slots[] = { 8117db96d56Sopenharmony_ci {Py_tp_doc, (void *)profiler_doc}, 8127db96d56Sopenharmony_ci {Py_tp_methods, profiler_methods}, 8137db96d56Sopenharmony_ci {Py_tp_dealloc, profiler_dealloc}, 8147db96d56Sopenharmony_ci {Py_tp_init, profiler_init}, 8157db96d56Sopenharmony_ci {Py_tp_traverse, profiler_traverse}, 8167db96d56Sopenharmony_ci {0, 0} 8177db96d56Sopenharmony_ci}; 8187db96d56Sopenharmony_ci 8197db96d56Sopenharmony_cistatic PyType_Spec _lsprof_profiler_type_spec = { 8207db96d56Sopenharmony_ci .name = "_lsprof.Profiler", 8217db96d56Sopenharmony_ci .basicsize = sizeof(ProfilerObject), 8227db96d56Sopenharmony_ci .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | 8237db96d56Sopenharmony_ci Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_IMMUTABLETYPE), 8247db96d56Sopenharmony_ci .slots = _lsprof_profiler_type_spec_slots, 8257db96d56Sopenharmony_ci}; 8267db96d56Sopenharmony_ci 8277db96d56Sopenharmony_cistatic PyMethodDef moduleMethods[] = { 8287db96d56Sopenharmony_ci {NULL, NULL} 8297db96d56Sopenharmony_ci}; 8307db96d56Sopenharmony_ci 8317db96d56Sopenharmony_cistatic int 8327db96d56Sopenharmony_ci_lsprof_traverse(PyObject *module, visitproc visit, void *arg) 8337db96d56Sopenharmony_ci{ 8347db96d56Sopenharmony_ci _lsprof_state *state = _lsprof_get_state(module); 8357db96d56Sopenharmony_ci Py_VISIT(state->profiler_type); 8367db96d56Sopenharmony_ci Py_VISIT(state->stats_entry_type); 8377db96d56Sopenharmony_ci Py_VISIT(state->stats_subentry_type); 8387db96d56Sopenharmony_ci return 0; 8397db96d56Sopenharmony_ci} 8407db96d56Sopenharmony_ci 8417db96d56Sopenharmony_cistatic int 8427db96d56Sopenharmony_ci_lsprof_clear(PyObject *module) 8437db96d56Sopenharmony_ci{ 8447db96d56Sopenharmony_ci _lsprof_state *state = _lsprof_get_state(module); 8457db96d56Sopenharmony_ci Py_CLEAR(state->profiler_type); 8467db96d56Sopenharmony_ci Py_CLEAR(state->stats_entry_type); 8477db96d56Sopenharmony_ci Py_CLEAR(state->stats_subentry_type); 8487db96d56Sopenharmony_ci return 0; 8497db96d56Sopenharmony_ci} 8507db96d56Sopenharmony_ci 8517db96d56Sopenharmony_cistatic void 8527db96d56Sopenharmony_ci_lsprof_free(void *module) 8537db96d56Sopenharmony_ci{ 8547db96d56Sopenharmony_ci _lsprof_clear((PyObject *)module); 8557db96d56Sopenharmony_ci} 8567db96d56Sopenharmony_ci 8577db96d56Sopenharmony_cistatic int 8587db96d56Sopenharmony_ci_lsprof_exec(PyObject *module) 8597db96d56Sopenharmony_ci{ 8607db96d56Sopenharmony_ci _lsprof_state *state = PyModule_GetState(module); 8617db96d56Sopenharmony_ci 8627db96d56Sopenharmony_ci state->profiler_type = (PyTypeObject *)PyType_FromModuleAndSpec( 8637db96d56Sopenharmony_ci module, &_lsprof_profiler_type_spec, NULL); 8647db96d56Sopenharmony_ci if (state->profiler_type == NULL) { 8657db96d56Sopenharmony_ci return -1; 8667db96d56Sopenharmony_ci } 8677db96d56Sopenharmony_ci 8687db96d56Sopenharmony_ci if (PyModule_AddType(module, state->profiler_type) < 0) { 8697db96d56Sopenharmony_ci return -1; 8707db96d56Sopenharmony_ci } 8717db96d56Sopenharmony_ci 8727db96d56Sopenharmony_ci state->stats_entry_type = PyStructSequence_NewType(&profiler_entry_desc); 8737db96d56Sopenharmony_ci if (state->stats_entry_type == NULL) { 8747db96d56Sopenharmony_ci return -1; 8757db96d56Sopenharmony_ci } 8767db96d56Sopenharmony_ci if (PyModule_AddType(module, state->stats_entry_type) < 0) { 8777db96d56Sopenharmony_ci return -1; 8787db96d56Sopenharmony_ci } 8797db96d56Sopenharmony_ci 8807db96d56Sopenharmony_ci state->stats_subentry_type = PyStructSequence_NewType(&profiler_subentry_desc); 8817db96d56Sopenharmony_ci if (state->stats_subentry_type == NULL) { 8827db96d56Sopenharmony_ci return -1; 8837db96d56Sopenharmony_ci } 8847db96d56Sopenharmony_ci if (PyModule_AddType(module, state->stats_subentry_type) < 0) { 8857db96d56Sopenharmony_ci return -1; 8867db96d56Sopenharmony_ci } 8877db96d56Sopenharmony_ci 8887db96d56Sopenharmony_ci return 0; 8897db96d56Sopenharmony_ci} 8907db96d56Sopenharmony_ci 8917db96d56Sopenharmony_cistatic PyModuleDef_Slot _lsprofslots[] = { 8927db96d56Sopenharmony_ci {Py_mod_exec, _lsprof_exec}, 8937db96d56Sopenharmony_ci {0, NULL} 8947db96d56Sopenharmony_ci}; 8957db96d56Sopenharmony_ci 8967db96d56Sopenharmony_cistatic struct PyModuleDef _lsprofmodule = { 8977db96d56Sopenharmony_ci PyModuleDef_HEAD_INIT, 8987db96d56Sopenharmony_ci .m_name = "_lsprof", 8997db96d56Sopenharmony_ci .m_doc = "Fast profiler", 9007db96d56Sopenharmony_ci .m_size = sizeof(_lsprof_state), 9017db96d56Sopenharmony_ci .m_methods = moduleMethods, 9027db96d56Sopenharmony_ci .m_slots = _lsprofslots, 9037db96d56Sopenharmony_ci .m_traverse = _lsprof_traverse, 9047db96d56Sopenharmony_ci .m_clear = _lsprof_clear, 9057db96d56Sopenharmony_ci .m_free = _lsprof_free 9067db96d56Sopenharmony_ci}; 9077db96d56Sopenharmony_ci 9087db96d56Sopenharmony_ciPyMODINIT_FUNC 9097db96d56Sopenharmony_ciPyInit__lsprof(void) 9107db96d56Sopenharmony_ci{ 9117db96d56Sopenharmony_ci return PyModuleDef_Init(&_lsprofmodule); 9127db96d56Sopenharmony_ci} 913