14710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#include "Python.h" 24710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#include "compile.h" 34710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#include "frameobject.h" 44710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#include "structseq.h" 54710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#include "rotatingtree.h" 64710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 74710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#if !defined(HAVE_LONG_LONG) 84710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#error "This module requires long longs!" 94710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#endif 104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm/*** Selection of a high-precision timer ***/ 124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#ifdef MS_WINDOWS 144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#include <windows.h> 164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PY_LONG_LONG 184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmhpTimer(void) 194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{ 204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm LARGE_INTEGER li; 214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm QueryPerformanceCounter(&li); 224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return li.QuadPart; 234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} 244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic double 264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmhpTimerUnit(void) 274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{ 284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm LARGE_INTEGER li; 294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (QueryPerformanceFrequency(&li)) 304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return 1.0 / li.QuadPart; 314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm else 324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return 0.000001; /* unlikely */ 334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} 344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#else /* !MS_WINDOWS */ 364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#ifndef HAVE_GETTIMEOFDAY 384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#error "This module requires gettimeofday() on non-Windows platforms!" 394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#endif 404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#if (defined(PYOS_OS2) && defined(PYCC_GCC)) 424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#include <sys/time.h> 434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#else 444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#include <sys/resource.h> 454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#include <sys/times.h> 464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#endif 474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PY_LONG_LONG 494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmhpTimer(void) 504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{ 514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm struct timeval tv; 524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PY_LONG_LONG ret; 534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#ifdef GETTIMEOFDAY_NO_TZ 544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm gettimeofday(&tv); 554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#else 564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm gettimeofday(&tv, (struct timezone *)NULL); 574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#endif 584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ret = tv.tv_sec; 594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ret = ret * 1000000 + tv.tv_usec; 604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return ret; 614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} 624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic double 644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmhpTimerUnit(void) 654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{ 664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return 0.000001; 674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} 684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#endif /* MS_WINDOWS */ 704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm/************************************************************/ 724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm/* Written by Brett Rosen and Ted Czotter */ 734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstruct _ProfilerEntry; 754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm/* represents a function called from another function */ 774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmtypedef struct _ProfilerSubEntry { 784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm rotating_node_t header; 794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PY_LONG_LONG tt; 804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PY_LONG_LONG it; 814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm long callcount; 824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm long recursivecallcount; 834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm long recursionLevel; 844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} ProfilerSubEntry; 854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm/* represents a function or user defined block */ 874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmtypedef struct _ProfilerEntry { 884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm rotating_node_t header; 894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyObject *userObj; /* PyCodeObject, or a descriptive str for builtins */ 904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PY_LONG_LONG tt; /* total time in this entry */ 914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PY_LONG_LONG it; /* inline time in this entry (not in subcalls) */ 924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm long callcount; /* how many times this was called */ 934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm long recursivecallcount; /* how many times called recursively */ 944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm long recursionLevel; 954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm rotating_node_t *calls; 964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} ProfilerEntry; 974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmtypedef struct _ProfilerContext { 994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PY_LONG_LONG t0; 1004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PY_LONG_LONG subt; 1014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm struct _ProfilerContext *previous; 1024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ProfilerEntry *ctxEntry; 1034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} ProfilerContext; 1044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmtypedef struct { 1064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyObject_HEAD 1074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm rotating_node_t *profilerEntries; 1084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ProfilerContext *currentProfilerContext; 1094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ProfilerContext *freelistProfilerContext; 1104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm int flags; 1114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyObject *externalTimer; 1124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm double externalTimerUnit; 1134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} ProfilerObject; 1144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#define POF_ENABLED 0x001 1164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#define POF_SUBCALLS 0x002 1174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#define POF_BUILTINS 0x004 1184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#define POF_NOMEMORY 0x100 1194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstaticforward PyTypeObject PyProfiler_Type; 1214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#define PyProfiler_Check(op) PyObject_TypeCheck(op, &PyProfiler_Type) 1234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#define PyProfiler_CheckExact(op) (Py_TYPE(op) == &PyProfiler_Type) 1244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm/*** External Timers ***/ 1264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#define DOUBLE_TIMER_PRECISION 4294967296.0 1284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject *empty_tuple; 1294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PY_LONG_LONG CallExternalTimer(ProfilerObject *pObj) 1314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{ 1324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PY_LONG_LONG result; 1334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyObject *o = PyObject_Call(pObj->externalTimer, empty_tuple, NULL); 1344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (o == NULL) { 1354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyErr_WriteUnraisable(pObj->externalTimer); 1364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return 0; 1374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 1384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (pObj->externalTimerUnit > 0.0) { 1394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm /* interpret the result as an integer that will be scaled 1404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm in profiler_getstats() */ 1414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm result = PyLong_AsLongLong(o); 1424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 1434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm else { 1444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm /* interpret the result as a double measured in seconds. 1454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm As the profiler works with PY_LONG_LONG internally 1464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm we convert it to a large integer */ 1474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm double val = PyFloat_AsDouble(o); 1484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm /* error handling delayed to the code below */ 1494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm result = (PY_LONG_LONG) (val * DOUBLE_TIMER_PRECISION); 1504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 1514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Py_DECREF(o); 1524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (PyErr_Occurred()) { 1534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyErr_WriteUnraisable(pObj->externalTimer); 1544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return 0; 1554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 1564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return result; 1574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} 1584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#define CALL_TIMER(pObj) ((pObj)->externalTimer ? \ 1604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm CallExternalTimer(pObj) : \ 1614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm hpTimer()) 1624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm/*** ProfilerObject ***/ 1644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject * 1664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmnormalizeUserObj(PyObject *obj) 1674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{ 1684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyCFunctionObject *fn; 1694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (!PyCFunction_Check(obj)) { 1704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Py_INCREF(obj); 1714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return obj; 1724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 1734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm /* Replace built-in function objects with a descriptive string 1744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm because of built-in methods -- keeping a reference to 1754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm __self__ is probably not a good idea. */ 1764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm fn = (PyCFunctionObject *)obj; 1774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (fn->m_self == NULL) { 1794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm /* built-in function: look up the module name */ 1804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyObject *mod = fn->m_module; 1814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm char *modname; 1824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (mod && PyString_Check(mod)) { 1834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm modname = PyString_AS_STRING(mod); 1844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 1854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm else if (mod && PyModule_Check(mod)) { 1864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm modname = PyModule_GetName(mod); 1874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (modname == NULL) { 1884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyErr_Clear(); 1894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm modname = "__builtin__"; 1904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 1914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 1924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm else { 1934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm modname = "__builtin__"; 1944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 1954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (strcmp(modname, "__builtin__") != 0) 1964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return PyString_FromFormat("<%s.%s>", 1974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm modname, 1984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm fn->m_ml->ml_name); 1994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm else 2004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return PyString_FromFormat("<%s>", 2014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm fn->m_ml->ml_name); 2024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 2034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm else { 2044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm /* built-in method: try to return 2054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm repr(getattr(type(__self__), __name__)) 2064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm */ 2074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyObject *self = fn->m_self; 2084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyObject *name = PyString_FromString(fn->m_ml->ml_name); 2094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (name != NULL) { 2104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyObject *mo = _PyType_Lookup(Py_TYPE(self), name); 2114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Py_XINCREF(mo); 2124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Py_DECREF(name); 2134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (mo != NULL) { 2144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyObject *res = PyObject_Repr(mo); 2154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Py_DECREF(mo); 2164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (res != NULL) 2174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return res; 2184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 2194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 2204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyErr_Clear(); 2214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return PyString_FromFormat("<built-in method %s>", 2224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm fn->m_ml->ml_name); 2234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 2244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} 2254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 2264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic ProfilerEntry* 2274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmnewProfilerEntry(ProfilerObject *pObj, void *key, PyObject *userObj) 2284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{ 2294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ProfilerEntry *self; 2304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self = (ProfilerEntry*) malloc(sizeof(ProfilerEntry)); 2314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (self == NULL) { 2324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm pObj->flags |= POF_NOMEMORY; 2334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return NULL; 2344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 2354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm userObj = normalizeUserObj(userObj); 2364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (userObj == NULL) { 2374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyErr_Clear(); 2384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm free(self); 2394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm pObj->flags |= POF_NOMEMORY; 2404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return NULL; 2414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 2424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->header.key = key; 2434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->userObj = userObj; 2444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->tt = 0; 2454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->it = 0; 2464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->callcount = 0; 2474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->recursivecallcount = 0; 2484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->recursionLevel = 0; 2494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->calls = EMPTY_ROTATING_TREE; 2504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm RotatingTree_Add(&pObj->profilerEntries, &self->header); 2514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return self; 2524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} 2534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 2544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic ProfilerEntry* 2554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmgetEntry(ProfilerObject *pObj, void *key) 2564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{ 2574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return (ProfilerEntry*) RotatingTree_Get(&pObj->profilerEntries, key); 2584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} 2594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 2604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic ProfilerSubEntry * 2614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmgetSubEntry(ProfilerObject *pObj, ProfilerEntry *caller, ProfilerEntry* entry) 2624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{ 2634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return (ProfilerSubEntry*) RotatingTree_Get(&caller->calls, 2644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm (void *)entry); 2654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} 2664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 2674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic ProfilerSubEntry * 2684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmnewSubEntry(ProfilerObject *pObj, ProfilerEntry *caller, ProfilerEntry* entry) 2694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{ 2704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ProfilerSubEntry *self; 2714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self = (ProfilerSubEntry*) malloc(sizeof(ProfilerSubEntry)); 2724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (self == NULL) { 2734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm pObj->flags |= POF_NOMEMORY; 2744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return NULL; 2754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 2764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->header.key = (void *)entry; 2774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->tt = 0; 2784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->it = 0; 2794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->callcount = 0; 2804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->recursivecallcount = 0; 2814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->recursionLevel = 0; 2824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm RotatingTree_Add(&caller->calls, &self->header); 2834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return self; 2844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} 2854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 2864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic int freeSubEntry(rotating_node_t *header, void *arg) 2874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{ 2884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ProfilerSubEntry *subentry = (ProfilerSubEntry*) header; 2894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm free(subentry); 2904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return 0; 2914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} 2924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 2934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic int freeEntry(rotating_node_t *header, void *arg) 2944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{ 2954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ProfilerEntry *entry = (ProfilerEntry*) header; 2964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm RotatingTree_Enum(entry->calls, freeSubEntry, NULL); 2974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Py_DECREF(entry->userObj); 2984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm free(entry); 2994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return 0; 3004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} 3014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 3024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic void clearEntries(ProfilerObject *pObj) 3034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{ 3044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm RotatingTree_Enum(pObj->profilerEntries, freeEntry, NULL); 3054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm pObj->profilerEntries = EMPTY_ROTATING_TREE; 3064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm /* release the memory hold by the ProfilerContexts */ 3074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (pObj->currentProfilerContext) { 3084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm free(pObj->currentProfilerContext); 3094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm pObj->currentProfilerContext = NULL; 3104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 3114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm while (pObj->freelistProfilerContext) { 3124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ProfilerContext *c = pObj->freelistProfilerContext; 3134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm pObj->freelistProfilerContext = c->previous; 3144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm free(c); 3154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 3164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm pObj->freelistProfilerContext = NULL; 3174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} 3184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 3194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic void 3204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylminitContext(ProfilerObject *pObj, ProfilerContext *self, ProfilerEntry *entry) 3214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{ 3224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->ctxEntry = entry; 3234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->subt = 0; 3244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->previous = pObj->currentProfilerContext; 3254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm pObj->currentProfilerContext = self; 3264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ++entry->recursionLevel; 3274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if ((pObj->flags & POF_SUBCALLS) && self->previous) { 3284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm /* find or create an entry for me in my caller's entry */ 3294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ProfilerEntry *caller = self->previous->ctxEntry; 3304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ProfilerSubEntry *subentry = getSubEntry(pObj, caller, entry); 3314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (subentry == NULL) 3324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm subentry = newSubEntry(pObj, caller, entry); 3334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (subentry) 3344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ++subentry->recursionLevel; 3354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 3364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->t0 = CALL_TIMER(pObj); 3374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} 3384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 3394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic void 3404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmStop(ProfilerObject *pObj, ProfilerContext *self, ProfilerEntry *entry) 3414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{ 3424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PY_LONG_LONG tt = CALL_TIMER(pObj) - self->t0; 3434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PY_LONG_LONG it = tt - self->subt; 3444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (self->previous) 3454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->previous->subt += tt; 3464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm pObj->currentProfilerContext = self->previous; 3474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (--entry->recursionLevel == 0) 3484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm entry->tt += tt; 3494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm else 3504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ++entry->recursivecallcount; 3514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm entry->it += it; 3524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm entry->callcount++; 3534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if ((pObj->flags & POF_SUBCALLS) && self->previous) { 3544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm /* find or create an entry for me in my caller's entry */ 3554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ProfilerEntry *caller = self->previous->ctxEntry; 3564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ProfilerSubEntry *subentry = getSubEntry(pObj, caller, entry); 3574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (subentry) { 3584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (--subentry->recursionLevel == 0) 3594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm subentry->tt += tt; 3604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm else 3614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ++subentry->recursivecallcount; 3624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm subentry->it += it; 3634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ++subentry->callcount; 3644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 3654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 3664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} 3674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 3684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic void 3694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmptrace_enter_call(PyObject *self, void *key, PyObject *userObj) 3704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{ 3714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm /* entering a call to the function identified by 'key' 3724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm (which can be a PyCodeObject or a PyMethodDef pointer) */ 3734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ProfilerObject *pObj = (ProfilerObject*)self; 3744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ProfilerEntry *profEntry; 3754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ProfilerContext *pContext; 3764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 3774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm /* In the case of entering a generator expression frame via a 3784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * throw (gen_send_ex(.., 1)), we may already have an 3794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * Exception set here. We must not mess around with this 3804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * exception, and some of the code under here assumes that 3814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * PyErr_* is its own to mess around with, so we have to 3824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * save and restore any current exception. */ 3834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyObject *last_type, *last_value, *last_tb; 3844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyErr_Fetch(&last_type, &last_value, &last_tb); 3854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 3864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm profEntry = getEntry(pObj, key); 3874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (profEntry == NULL) { 3884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm profEntry = newProfilerEntry(pObj, key, userObj); 3894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (profEntry == NULL) 3904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm goto restorePyerr; 3914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 3924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm /* grab a ProfilerContext out of the free list */ 3934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm pContext = pObj->freelistProfilerContext; 3944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (pContext) { 3954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm pObj->freelistProfilerContext = pContext->previous; 3964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 3974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm else { 3984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm /* free list exhausted, allocate a new one */ 3994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm pContext = (ProfilerContext*) 4004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm malloc(sizeof(ProfilerContext)); 4014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (pContext == NULL) { 4024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm pObj->flags |= POF_NOMEMORY; 4034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm goto restorePyerr; 4044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 4054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 4064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm initContext(pObj, pContext, profEntry); 4074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 4084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmrestorePyerr: 4094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyErr_Restore(last_type, last_value, last_tb); 4104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} 4114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 4124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic void 4134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmptrace_leave_call(PyObject *self, void *key) 4144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{ 4154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm /* leaving a call to the function identified by 'key' */ 4164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ProfilerObject *pObj = (ProfilerObject*)self; 4174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ProfilerEntry *profEntry; 4184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ProfilerContext *pContext; 4194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 4204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm pContext = pObj->currentProfilerContext; 4214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (pContext == NULL) 4224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return; 4234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm profEntry = getEntry(pObj, key); 4244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (profEntry) { 4254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Stop(pObj, pContext, profEntry); 4264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 4274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm else { 4284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm pObj->currentProfilerContext = pContext->previous; 4294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 4304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm /* put pContext into the free list */ 4314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm pContext->previous = pObj->freelistProfilerContext; 4324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm pObj->freelistProfilerContext = pContext; 4334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} 4344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 4354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic int 4364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmprofiler_callback(PyObject *self, PyFrameObject *frame, int what, 4374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyObject *arg) 4384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{ 4394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm switch (what) { 4404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 4414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm /* the 'frame' of a called function is about to start its execution */ 4424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm case PyTrace_CALL: 4434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ptrace_enter_call(self, (void *)frame->f_code, 4444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm (PyObject *)frame->f_code); 4454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm break; 4464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 4474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm /* the 'frame' of a called function is about to finish 4484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm (either normally or with an exception) */ 4494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm case PyTrace_RETURN: 4504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ptrace_leave_call(self, (void *)frame->f_code); 4514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm break; 4524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 4534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm /* case PyTrace_EXCEPTION: 4544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm If the exception results in the function exiting, a 4554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyTrace_RETURN event will be generated, so we don't need to 4564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm handle it. */ 4574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 4584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#ifdef PyTrace_C_CALL /* not defined in Python <= 2.3 */ 4594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm /* the Python function 'frame' is issuing a call to the built-in 4604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm function 'arg' */ 4614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm case PyTrace_C_CALL: 4624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if ((((ProfilerObject *)self)->flags & POF_BUILTINS) 4634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm && PyCFunction_Check(arg)) { 4644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ptrace_enter_call(self, 4654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ((PyCFunctionObject *)arg)->m_ml, 4664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm arg); 4674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 4684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm break; 4694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 4704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm /* the call to the built-in function 'arg' is returning into its 4714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm caller 'frame' */ 4724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm case PyTrace_C_RETURN: /* ...normally */ 4734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm case PyTrace_C_EXCEPTION: /* ...with an exception set */ 4744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if ((((ProfilerObject *)self)->flags & POF_BUILTINS) 4754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm && PyCFunction_Check(arg)) { 4764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ptrace_leave_call(self, 4774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ((PyCFunctionObject *)arg)->m_ml); 4784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 4794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm break; 4804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#endif 4814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 4824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm default: 4834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm break; 4844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 4854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return 0; 4864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} 4874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 4884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic int 4894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmpending_exception(ProfilerObject *pObj) 4904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{ 4914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (pObj->flags & POF_NOMEMORY) { 4924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm pObj->flags -= POF_NOMEMORY; 4934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyErr_SetString(PyExc_MemoryError, 4944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm "memory was exhausted while profiling"); 4954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return -1; 4964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 4974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return 0; 4984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} 4994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 5004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm/************************************************************/ 5014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 5024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyStructSequence_Field profiler_entry_fields[] = { 5034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm {"code", "code object or built-in function name"}, 5044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm {"callcount", "how many times this was called"}, 5054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm {"reccallcount", "how many times called recursively"}, 5064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm {"totaltime", "total time in this entry"}, 5074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm {"inlinetime", "inline time in this entry (not in subcalls)"}, 5084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm {"calls", "details of the calls"}, 5094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm {0} 5104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}; 5114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 5124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyStructSequence_Field profiler_subentry_fields[] = { 5134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm {"code", "called code object or built-in function name"}, 5144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm {"callcount", "how many times this is called"}, 5154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm {"reccallcount", "how many times this is called recursively"}, 5164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm {"totaltime", "total time spent in this call"}, 5174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm {"inlinetime", "inline time (not in further subcalls)"}, 5184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm {0} 5194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}; 5204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 5214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyStructSequence_Desc profiler_entry_desc = { 5224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm "_lsprof.profiler_entry", /* name */ 5234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm NULL, /* doc */ 5244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm profiler_entry_fields, 5254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 6 5264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}; 5274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 5284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyStructSequence_Desc profiler_subentry_desc = { 5294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm "_lsprof.profiler_subentry", /* name */ 5304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm NULL, /* doc */ 5314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm profiler_subentry_fields, 5324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 5 5334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}; 5344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 5354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic int initialized; 5364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyTypeObject StatsEntryType; 5374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyTypeObject StatsSubEntryType; 5384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 5394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 5404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmtypedef struct { 5414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyObject *list; 5424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyObject *sublist; 5434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm double factor; 5444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} statscollector_t; 5454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 5464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic int statsForSubEntry(rotating_node_t *node, void *arg) 5474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{ 5484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ProfilerSubEntry *sentry = (ProfilerSubEntry*) node; 5494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm statscollector_t *collect = (statscollector_t*) arg; 5504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ProfilerEntry *entry = (ProfilerEntry*) sentry->header.key; 5514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm int err; 5524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyObject *sinfo; 5534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm sinfo = PyObject_CallFunction((PyObject*) &StatsSubEntryType, 5544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm "((Olldd))", 5554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm entry->userObj, 5564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm sentry->callcount, 5574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm sentry->recursivecallcount, 5584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm collect->factor * sentry->tt, 5594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm collect->factor * sentry->it); 5604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (sinfo == NULL) 5614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return -1; 5624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm err = PyList_Append(collect->sublist, sinfo); 5634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Py_DECREF(sinfo); 5644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return err; 5654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} 5664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 5674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic int statsForEntry(rotating_node_t *node, void *arg) 5684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{ 5694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ProfilerEntry *entry = (ProfilerEntry*) node; 5704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm statscollector_t *collect = (statscollector_t*) arg; 5714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyObject *info; 5724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm int err; 5734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (entry->callcount == 0) 5744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return 0; /* skip */ 5754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 5764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (entry->calls != EMPTY_ROTATING_TREE) { 5774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm collect->sublist = PyList_New(0); 5784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (collect->sublist == NULL) 5794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return -1; 5804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (RotatingTree_Enum(entry->calls, 5814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm statsForSubEntry, collect) != 0) { 5824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Py_DECREF(collect->sublist); 5834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return -1; 5844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 5854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 5864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm else { 5874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Py_INCREF(Py_None); 5884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm collect->sublist = Py_None; 5894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 5904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 5914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm info = PyObject_CallFunction((PyObject*) &StatsEntryType, 5924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm "((OllddO))", 5934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm entry->userObj, 5944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm entry->callcount, 5954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm entry->recursivecallcount, 5964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm collect->factor * entry->tt, 5974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm collect->factor * entry->it, 5984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm collect->sublist); 5994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Py_DECREF(collect->sublist); 6004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (info == NULL) 6014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return -1; 6024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm err = PyList_Append(collect->list, info); 6034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Py_DECREF(info); 6044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return err; 6054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} 6064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 6074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmPyDoc_STRVAR(getstats_doc, "\ 6084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmgetstats() -> list of profiler_entry objects\n\ 6094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm\n\ 6104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmReturn all information collected by the profiler.\n\ 6114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmEach profiler_entry is a tuple-like object with the\n\ 6124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmfollowing attributes:\n\ 6134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm\n\ 6144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm code code object\n\ 6154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm callcount how many times this was called\n\ 6164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm reccallcount how many times called recursively\n\ 6174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm totaltime total time in this entry\n\ 6184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm inlinetime inline time in this entry (not in subcalls)\n\ 6194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm calls details of the calls\n\ 6204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm\n\ 6214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmThe calls attribute is either None or a list of\n\ 6224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmprofiler_subentry objects:\n\ 6234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm\n\ 6244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm code called code object\n\ 6254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm callcount how many times this is called\n\ 6264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm reccallcount how many times this is called recursively\n\ 6274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm totaltime total time spent in this call\n\ 6284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm inlinetime inline time (not in further subcalls)\n\ 6294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm"); 6304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 6314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject* 6324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmprofiler_getstats(ProfilerObject *pObj, PyObject* noarg) 6334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{ 6344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm statscollector_t collect; 6354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (pending_exception(pObj)) 6364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return NULL; 6374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (!pObj->externalTimer) 6384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm collect.factor = hpTimerUnit(); 6394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm else if (pObj->externalTimerUnit > 0.0) 6404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm collect.factor = pObj->externalTimerUnit; 6414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm else 6424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm collect.factor = 1.0 / DOUBLE_TIMER_PRECISION; 6434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm collect.list = PyList_New(0); 6444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (collect.list == NULL) 6454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return NULL; 6464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (RotatingTree_Enum(pObj->profilerEntries, statsForEntry, &collect) 6474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm != 0) { 6484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Py_DECREF(collect.list); 6494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return NULL; 6504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 6514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return collect.list; 6524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} 6534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 6544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic int 6554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmsetSubcalls(ProfilerObject *pObj, int nvalue) 6564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{ 6574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (nvalue == 0) 6584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm pObj->flags &= ~POF_SUBCALLS; 6594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm else if (nvalue > 0) 6604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm pObj->flags |= POF_SUBCALLS; 6614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return 0; 6624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} 6634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 6644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic int 6654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmsetBuiltins(ProfilerObject *pObj, int nvalue) 6664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{ 6674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (nvalue == 0) 6684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm pObj->flags &= ~POF_BUILTINS; 6694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm else if (nvalue > 0) { 6704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#ifndef PyTrace_C_CALL 6714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyErr_SetString(PyExc_ValueError, 6724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm "builtins=True requires Python >= 2.4"); 6734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return -1; 6744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#else 6754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm pObj->flags |= POF_BUILTINS; 6764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#endif 6774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 6784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return 0; 6794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} 6804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 6814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmPyDoc_STRVAR(enable_doc, "\ 6824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmenable(subcalls=True, builtins=True)\n\ 6834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm\n\ 6844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmStart collecting profiling information.\n\ 6854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmIf 'subcalls' is True, also records for each function\n\ 6864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatistics separated according to its current caller.\n\ 6874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmIf 'builtins' is True, records the time spent in\n\ 6884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmbuilt-in functions separately from their caller.\n\ 6894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm"); 6904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 6914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject* 6924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmprofiler_enable(ProfilerObject *self, PyObject *args, PyObject *kwds) 6934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{ 6944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm int subcalls = -1; 6954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm int builtins = -1; 6964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm static char *kwlist[] = {"subcalls", "builtins", 0}; 6974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (!PyArg_ParseTupleAndKeywords(args, kwds, "|ii:enable", 6984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm kwlist, &subcalls, &builtins)) 6994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return NULL; 7004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (setSubcalls(self, subcalls) < 0 || setBuiltins(self, builtins) < 0) 7014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return NULL; 7024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyEval_SetProfile(profiler_callback, (PyObject*)self); 7034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->flags |= POF_ENABLED; 7044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Py_INCREF(Py_None); 7054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return Py_None; 7064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} 7074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 7084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic void 7094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmflush_unmatched(ProfilerObject *pObj) 7104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{ 7114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm while (pObj->currentProfilerContext) { 7124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ProfilerContext *pContext = pObj->currentProfilerContext; 7134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ProfilerEntry *profEntry= pContext->ctxEntry; 7144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (profEntry) 7154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Stop(pObj, pContext, profEntry); 7164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm else 7174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm pObj->currentProfilerContext = pContext->previous; 7184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (pContext) 7194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm free(pContext); 7204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 7214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 7224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} 7234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 7244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmPyDoc_STRVAR(disable_doc, "\ 7254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdisable()\n\ 7264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm\n\ 7274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmStop collecting profiling information.\n\ 7284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm"); 7294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 7304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject* 7314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmprofiler_disable(ProfilerObject *self, PyObject* noarg) 7324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{ 7334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->flags &= ~POF_ENABLED; 7344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyEval_SetProfile(NULL, NULL); 7354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm flush_unmatched(self); 7364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (pending_exception(self)) 7374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return NULL; 7384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Py_INCREF(Py_None); 7394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return Py_None; 7404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} 7414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 7424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmPyDoc_STRVAR(clear_doc, "\ 7434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclear()\n\ 7444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm\n\ 7454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmClear all profiling information collected so far.\n\ 7464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm"); 7474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 7484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyObject* 7494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmprofiler_clear(ProfilerObject *pObj, PyObject* noarg) 7504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{ 7514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm clearEntries(pObj); 7524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Py_INCREF(Py_None); 7534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return Py_None; 7544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} 7554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 7564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic void 7574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmprofiler_dealloc(ProfilerObject *op) 7584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{ 7594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (op->flags & POF_ENABLED) 7604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyEval_SetProfile(NULL, NULL); 7614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm flush_unmatched(op); 7624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm clearEntries(op); 7634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Py_XDECREF(op->externalTimer); 7644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Py_TYPE(op)->tp_free(op); 7654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} 7664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 7674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic int 7684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmprofiler_init(ProfilerObject *pObj, PyObject *args, PyObject *kw) 7694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{ 7704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyObject *o; 7714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyObject *timer = NULL; 7724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm double timeunit = 0.0; 7734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm int subcalls = 1; 7744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#ifdef PyTrace_C_CALL 7754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm int builtins = 1; 7764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#else 7774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm int builtins = 0; 7784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#endif 7794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm static char *kwlist[] = {"timer", "timeunit", 7804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm "subcalls", "builtins", 0}; 7814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 7824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (!PyArg_ParseTupleAndKeywords(args, kw, "|Odii:Profiler", kwlist, 7834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm &timer, &timeunit, 7844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm &subcalls, &builtins)) 7854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return -1; 7864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 7874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (setSubcalls(pObj, subcalls) < 0 || setBuiltins(pObj, builtins) < 0) 7884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return -1; 7894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm o = pObj->externalTimer; 7904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm pObj->externalTimer = timer; 7914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Py_XINCREF(timer); 7924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Py_XDECREF(o); 7934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm pObj->externalTimerUnit = timeunit; 7944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return 0; 7954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} 7964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 7974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyMethodDef profiler_methods[] = { 7984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm {"getstats", (PyCFunction)profiler_getstats, 7994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm METH_NOARGS, getstats_doc}, 8004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm {"enable", (PyCFunction)profiler_enable, 8014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm METH_VARARGS | METH_KEYWORDS, enable_doc}, 8024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm {"disable", (PyCFunction)profiler_disable, 8034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm METH_NOARGS, disable_doc}, 8044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm {"clear", (PyCFunction)profiler_clear, 8054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm METH_NOARGS, clear_doc}, 8064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm {NULL, NULL} 8074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}; 8084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 8094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmPyDoc_STRVAR(profiler_doc, "\ 8104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmProfiler(custom_timer=None, time_unit=None, subcalls=True, builtins=True)\n\ 8114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm\n\ 8124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Builds a profiler object using the specified timer function.\n\ 8134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm The default timer is a fast built-in one based on real time.\n\ 8144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm For custom timer functions returning integers, time_unit can\n\ 8154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm be a float specifying a scale (i.e. how long each integer unit\n\ 8164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm is, in seconds).\n\ 8174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm"); 8184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 8194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatichere PyTypeObject PyProfiler_Type = { 8204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyObject_HEAD_INIT(NULL) 8214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* ob_size */ 8224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm "_lsprof.Profiler", /* tp_name */ 8234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm sizeof(ProfilerObject), /* tp_basicsize */ 8244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_itemsize */ 8254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm (destructor)profiler_dealloc, /* tp_dealloc */ 8264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_print */ 8274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_getattr */ 8284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_setattr */ 8294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_compare */ 8304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_repr */ 8314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_as_number */ 8324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_as_sequence */ 8334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_as_mapping */ 8344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_hash */ 8354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_call */ 8364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_str */ 8374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_getattro */ 8384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_setattro */ 8394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_as_buffer */ 8404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ 8414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm profiler_doc, /* tp_doc */ 8424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_traverse */ 8434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_clear */ 8444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_richcompare */ 8454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_weaklistoffset */ 8464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_iter */ 8474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_iternext */ 8484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm profiler_methods, /* tp_methods */ 8494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_members */ 8504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_getset */ 8514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_base */ 8524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_dict */ 8534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_descr_get */ 8544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_descr_set */ 8554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_dictoffset */ 8564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm (initproc)profiler_init, /* tp_init */ 8574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyType_GenericAlloc, /* tp_alloc */ 8584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyType_GenericNew, /* tp_new */ 8594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyObject_Del, /* tp_free */ 8604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}; 8614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 8624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyMethodDef moduleMethods[] = { 8634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm {NULL, NULL} 8644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}; 8654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 8664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmPyMODINIT_FUNC 8674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylminit_lsprof(void) 8684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{ 8694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyObject *module, *d; 8704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm module = Py_InitModule3("_lsprof", moduleMethods, "Fast profiler"); 8714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (module == NULL) 8724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return; 8734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm d = PyModule_GetDict(module); 8744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (PyType_Ready(&PyProfiler_Type) < 0) 8754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return; 8764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyDict_SetItemString(d, "Profiler", (PyObject *)&PyProfiler_Type); 8774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 8784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (!initialized) { 8794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyStructSequence_InitType(&StatsEntryType, 8804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm &profiler_entry_desc); 8814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyStructSequence_InitType(&StatsSubEntryType, 8824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm &profiler_subentry_desc); 8834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 8844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Py_INCREF((PyObject*) &StatsEntryType); 8854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Py_INCREF((PyObject*) &StatsSubEntryType); 8864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyModule_AddObject(module, "profiler_entry", 8874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm (PyObject*) &StatsEntryType); 8884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyModule_AddObject(module, "profiler_subentry", 8894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm (PyObject*) &StatsSubEntryType); 8904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm empty_tuple = PyTuple_New(0); 8914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm initialized = 1; 8924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} 893